GithubHelp home page GithubHelp logo

openforcefield / cmiles Goto Github PK

View Code? Open in Web Editor NEW
23.0 7.0 7.0 15.44 MB

Generate canonical molecule identifiers for quantum chemistry database

Home Page: https://cmiles.readthedocs.io

License: MIT License

Python 2.15% Batchfile 0.01% Shell 0.01% Jupyter Notebook 97.85%
cheminformatics quantum-chemistry forcefield forcefield-parameterization database

cmiles's Introduction

Status GH Actions Status Codecov coverage
Latest Release Last release tag Commits since releaseDOI
Communication docs stable user & dev discussions
Foundation license platforms python Funding
Installation Releases Conda Last updated Anaconda Cloud downloads

The Open Force Field toolkit

The Open Force Field Toolkit, built by the Open Force Field Initiative, is a Python toolkit for the development and application of modern molecular mechanics force fields based on direct chemical perception and rigorous statistical parameterization methods.

The toolkit currently covers two main areas we have committed to stably maintain throughout their lifetimes:

Note: Prior to version 0.9.0, this toolkit and its associated repository were named openforcefield and used different import paths. For details on this change and migration instructions, see the release notes of version 0.9.0.

Documentation

Documentation for the Open Force Field Toolkit is hosted at readthedocs. Example notebooks are available in the examples/ directory and also hosted on the Open Force Field website.

How to cite

Please cite the OpenFF Toolkit using the Zenodo record of the latest release or the version that was used. The BibTeX reference of the latest release can be found here.

Installation

The Open Force Field Toolkit (openff-toolkit) is a Python toolkit, and supports Python 3.9 through 3.11.

Installing via Mamba/Conda

Detailed installation instructions can be found here.

Force Fields

Two major force field development efforts have been undertaken by the Open Force Field Initiative, with results hosted in separate repositories.

  • The Open Force Fields repository, which features the Parsley and Sage force field lines. These are the Open Force Field Initiative's efforts toward building new force fields. The initial parameters are taken from smirnoff99Frosst, but software and data produced by the Initiative's efforts have been used to refit parameter values and add new SMIRKS-based parameters.
  • The smirnoff99Frosst repository, which is descended from AMBER's parm99 force field as well as Merck-Frosst's parm@frosst. This line of force fields does not aim to alter parameter values, but is instead a test of accurately converting an atom type-based force field to the SMIRNOFF format.

Force fields from both of these packages are available in their respective GitHub repositories and also as conda packages. Tables detailing the individual file names/versions within these force field lines are in the README of each repository. By default, installing the Open Force Field toolkit using conda or the single-file toolkit installers will also install these conda packages. A plugin architecture is provided for other force field developers to produce python/conda packages that can be imported by the Open Force Field Toolkit as well.

Toolkit features

The SMIRKS Native Open Force Field (SMIRNOFF) format

This repository provides tools for using the SMIRKS Native Open Force Field (SMIRNOFF) specification, which currently supports an XML representation for force field definition files.

By convention, files containing XML representations of SMIRNOFF force fields carry .offxml extensions.

Example SMIRNOFF .offxml force field definitions can be found in openff/toolkit/data/test_forcefields/. These force fields are for testing only, and we neither record versions of these files, nor do we guarantee their correctness or completeness.

Working with SMIRNOFF parameter sets

SMIRNOFF force fields can be parsed by the ForceField class, which offers methods including create_openmm_system for exporting to OpenMM and create_interchange for exporting to other formats (GROMACS, Amber, LAMMPS) via Interchange.

# Load a molecule into the OpenFF Molecule object
from openff.toolkit import Molecule
from openff.toolkit.utils import get_data_file_path
sdf_file_path = get_data_file_path('molecules/ethanol.sdf')
molecule = Molecule.from_file(sdf_file_path)

# Create an OpenFF Topology object from the molecule
from openff.toolkit import Topology
topology = Topology.from_molecules(molecule)

# Load the latest OpenFF force field release: version 2.1.0, codename "Sage"
from openff.toolkit import ForceField
forcefield = ForceField('openff-2.1.0.offxml')

# Create an OpenMM system representing the molecule with SMIRNOFF-applied parameters
openmm_system = forcefield.create_openmm_system(topology)

# Create an Interchange object for representations in other formats
interchange = forcefield.create_interchange(topology)

Detailed examples of using SMIRNOFF with the toolkit can be found in the documentation.

Frequently asked questions (FAQ)

See FAQ.md for answers to a variety of common problems, such as:

  • Why do I need to provide molecules corresponding to the components of my system, or a Topology with bond orders?
  • Can I use an Amber, CHARMM, or GROMACS topology/coordinate file as a starting point for applying a SMIRNOFF force field?
  • What if I am starting from a PDB file?

Contributors

For a partial list of contributors, see the GitHub Contributors page. Others whose work constitutes significant contributions but did not make it into the git history include Shuzhe Wang.

cmiles's People

Contributors

chayast avatar dependabot[bot] avatar j-wags avatar mattwthompson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

cmiles's Issues

Assigning formal charge can lead to changes in hydrogen counts

When loading a molecule for a QCArchive molecule where an atom should have a formal charge, the oechem.OEAssignFormalCharges(molecule) can add implicit hydrogens where we don't want them because it doesn't know the charge of the atom.

Example molecule:
image

When loading this molecule from an sdf file where the atoms have charge assigned to them, the canonical SMILES is:
'c1ccc(cc1)c2[n-]nnn2'
But when loading it from a QCArchive molecule in cmiles, the canonical SMILES is:
c1ccc(cc1)c2[nH]nnn2

cmiles.utils.to_canonical_label failure

The following code raises an exception:

>>> import cmiles
>>> cmiles.utils.to_canonical_label("[H:13][c:1]1[c:3]([n:8][c:5]([n:10][c:6]1[N:12]([H:19])[c:7]2[c:2]([c:4]([n:9][n:11]2[H:18])[H:16])[H:14])[H:17])[H:15]", (9, 5, 11, 5))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/choderaj/miniconda/lib/python3.7/site-packages/cmiles/utils.py", line 193, in to_canonical_label
    return toolkit.generate_index(mol, labeled_atoms)
  File "/Users/choderaj/miniconda/lib/python3.7/site-packages/cmiles/_cmiles_oe.py", line 203, in generate_index
    a.SetMapIdx(i + 1)
AttributeError: 'NoneType' object has no attribute 'SetMapIdx'

JSON input molecule

Add the ability to generate identifiers from QCSchema.

The minimum fields required to generate a molecular graph are different for RDKit and OpenEye.
For OpenEye, the minimum is either symbols and connectivity or symbols and geometry because OpenEye can perceive bonds and bond types from distance. However, the units need to be in Angstroms. @dgasmith, are the units in QCSchema always Bohr? Is there a way to ensure that?
If geometry exists we want to use it to make sure we get the stereochemistry right.

For RDKit, the connectivity table is needed. RDKit cannot perceive bonds from distance.

Discrepancies in re-generated reference data

I'm trying to hunt down how RDKit differences in recent versions affect this data and it seems that I cannot even re-generate the reference data to match the existing files

$ python generate_reference.py 2>/dev/null
2019.03.2
$ git diff --name-only | cat
cmiles/tests/reference/drug_bank_inchi_rd_2019.03.2.txt
cmiles/tests/reference/drug_bank_inchikey_rd_2019.03.2.txt
cmiles/tests/reference/drug_bank_mapped_smi_rd_2019.03.2.smi

The differences are fairy small, but it's concerning that there are any at all

Standardize molecule support through openforcefield.topology.Molecule?

A bunch of functions in cmiles and fragmenter support a random/arbitrary subset of QCSchema JSON, QCSchema dict, SMILES, OEMol, and RDKit Mol.

It would be very helpful to standardize support for all of these through the openforcefield.topology.Molecule class, which is now stable enough to use as a standard exchange format.

Hydrogens move and stereochemistry flip when reading qcschema molecule

@vtlim pointed out that the cmiles SMILES changed for this molecule.

client = ptl.FractalClient()

ds = client.get_collection('OptimizationDataset', 'OpenFF Full Optimization Benchmark 1')
entry = ds.get_entry(name='CO/N=C/1\C[N@](C[C@H]1C[NH3+])c2c(cc3c(=O)c(cn(c3n2)C4CC4)C(=O)[O-])F-3')
record = ds.get_record('CO/N=C/1\C[N@](C[C@H]1C[NH3+])c2c(cc3c(=O)c(cn(c3n2)C4CC4)C(=O)[O-])F-3', specification='default')
qc_mol = record.get_final_molecule()
qcjson_mol = qc_mol.dict(encoding='json')
oemol = cmiles.utils.load_molecule(qcjson_mol)

print("cmiles SMILES in database:")
print(entry.attributes['canonical_isomeric_smiles'])
print('cmiles SMILES after reading qcschema molecule')
print(cmiles.utils.mol_to_smiles(oemol, mapped=False, explicit_hydrogen=False))

Output:

cmiles SMILES in database:
CO/N=C/1\C[N@](C[C@H]1C[NH3+])c2c(cc3c(=O)c(cn(c3n2)C4CC4)C(=O)[O-])F
cmiles SMILES after reading qcschema molecule
CO/N=C/1\C[N@@H+](C[C@H]1CN)c2c(cc3c(=O)c(cn(c3n2)C4CC4)C(=O)[O-])F

There are 2 issues:

  1. A hydrogen moved from the NH3+ to the pyramidal nitrogen
  2. Stereochemistry changed for pyramidal nitrogen.

The first issue is fixed when this is commented out. It's not needed because cmiles already has the connectivity from the connectivity map. However, the bond is very long so openeye's perception is probably correct. These issues should be flagged with checking WBOs to see if the chemical graph changed.
After investigating the second issue, it turns out that the input molecule had the pyramidal nitrogen in a planar conformation and after optimization the pyramidal nitrogen had a specified stereochemistry which was apparently different than the input SMILES.

Input molecule:
Screen Shot 2019-11-27 at 10 44 04 AM

Optimized molecule:
Screen Shot 2019-11-27 at 10 44 08 AM

@j-wags, I think this means that cmiles should not require defined stereochemistry for pyramidal nitrogen given that they can flip.

Generating CMILES ids for an OEMol?

It looks like there's no direct way to generate CMILES ids for an OEMol. Instead, we have to go through the SMILES (which loses information about atom ordering) or QCSchema (which loses information about bonds).

    molecule_input: dict or str
        A JSON serialized QC molecule or an isomeric SMILES

Would it not be simple to generate the correct mapped SMILES from an OEMol, since we have the atom ordering and chemical information within the object?

Add examples that start with oemol/rdmol/qcschema

I wanted to use cmiles to store molecules so I can reliably store the molecules I'm using to test chemper and return to them. It turns out all I needed was cmiles.utils.mol_to_smiles(m). However, it took me a while to find that function.

The Jupyter notebooks in the "notebooks" folder seem to have complex corner cases, which are also important to be documented. When time allows I think it would be valuable to make an "example" notebook that has the more straight forward example that people might want to use this for. Or just still a couple of python snippets in the README. I started by trying to use the How to use cmiles section in the README, but I couldn't even find the function it mentions, to_molecule_id.

conda package

Is this repo at a point where we can create a conda package for cmiles?

Could it go into conda-forge?

RDKit 2020.09.3 changes

Tests are failing again after a new version of RDKit (OpenEye tests unaffected). Will run #46 again for these changes, documenting which molecules have changed behavior.

Explicit valence issue with rdkit

Hi folks,

please have a look at the following code snippet:

import qcportal as ptl
import cmiles

qc_client  = ptl.FractalClient("https://api.qcarchive.molssi.org:443/")
ds         = qc_client.get_collection('OptimizationDataset', "FDA Optimization Dataset 1")
qcrecord   = ds.get_record("C[NH2+]C[C@@H](c1ccc(c(c1)O)O)O-0", 
                           specification="default")
qcmol      = qcrecord.get_final_molecule()
oemol      = cmiles.utils.load_molecule(qcmol.dict(), toolkit="openeye")
rdmol      = cmiles.utils.load_molecule(qcmol.dict(), toolkit="rdkit")

The oemol is returned successfully, however rdmol cannot be created due to valence issues with N atoms: RDKit ERROR: [13:24:10] Explicit valence for atom # 9 N, 4, is greater than permitted. I think this is fixable with the following code block inserted after line 44 in cmiles/_cmiles_rd.py (not elegant though, won't cover general valence issues):

    # Fix N connectivity issue
    for atom_idx in range(em.GetNumAtoms()):
        atom = em.GetAtomWithIdx(atom_idx)
        if atom.GetAtomicNum() == 7:
            total_bo = 0.
            for bond in atom.GetBonds():
                total_bo += bond.GetBondTypeAsDouble()
            if total_bo > 3.:
                atom.SetFormalCharge(1)

Regards,
Tobias

Ideas for future refactor

This is a "master" issue for tracking various ideas relating to a future refactor:

  • What shall be included
  • What shall not be included
  • Relationship with the toolkit
  • What else?

I've also added a refactor tag to track other issues.

Remove duplicate `oechem.OEMol` in utils `_set_toolkit`

I was looking into utils to understand how molecule_to_smiles so I ended up looking at a line in _set_toolkit. There are two things, it looks like ochem.OEMol is in the list twice, but also oechem.OEMolBase is the parent class for OEMol and OEGraphMol so that should be the only thing you have to check I think.

Problem when loading TorsionDrive qcmol from QCA

Hi folks,

please have a look at the following code:

import qcportal as ptl
import cmiles

print(ptl.__version__)
print(cmiles.__version__)

qc_client  = ptl.FractalClient("https://api.qcarchive.molssi.org:443/")
ds         = qc_client.get_collection('TorsionDriveDataset', "OpenFF Substituted Phenyl Set 1")
qcrecord   = ds.get_record("CCC(=O)Nc1[cH:1][c:2](ccn1)[NH:3][CH2:4]C", 
                           specification="default")
qcmols     = qcrecord.get_final_molecules()

for torsion_crd, qcmol in qcmols.items():
    print(qcmol["symbols"].shape)
    print(qcmol["geometry"].shape)
    print(qcmol["symbols"].shape[0]==qcmol["geometry"].shape[0])
    oemol = cmiles.utils.load_molecule(qcmol, toolkit="openeye")

Fails with the following error:

v0.14.0
v0.1.6
(29,)
(29, 3)
True
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-7-f79a5682ac30> in <module>
     16 qcmols     = qcrecord.get_final_molecules()
     17 for torsion_crd, qcmol in qcmols.items():
---> 18     oemol = cmiles.utils.load_molecule(qcmol, toolkit="openeye")

~/progs/anaconda3/envs/atomtyping/lib/python3.7/site-packages/cmiles/utils.py in load_molecule(inp_molecule, toolkit, **kwargs)
     65     if isinstance(inp_molecule, dict):
     66         # This is a JSON molecule.
---> 67         molecule = mol_from_json(inp_molecule, toolkit=toolkit, **kwargs)
     68 
     69     elif isinstance(inp_molecule, str):

~/progs/anaconda3/envs/atomtyping/lib/python3.7/site-packages/cmiles/utils.py in mol_from_json(inp_molecule, toolkit, **kwargs)
    126     geometry = np.asarray(inp_molecule['geometry'], dtype=float)*BOHR_2_ANGSTROM
    127     if len(symbols) != geometry.shape[0]/3:
--> 128         raise ValueError("Number of atoms in molecule does not match length of position array")
    129 
    130     if toolkit == 'openeye' and has_openeye:

ValueError: Number of atoms in molecule does not match length of position array

The test qcmol in the example should be fine and the number of symbols matches the number of coordinates. I think the offending line must be changed to something like:

if symbols.shape[0] != geometry.shape[0]:
    raise ValueError("Number of atoms in molecule does not match length of position array")

Thanks,
Tobias

Canonical atom order without resorting to omega

We want to have a canonical order for the map indices in the mapped SMILES.
Currently, cmiles uses the setting omega.SetCanonOrder(True) and generates a conformer which has a canonical atom order that is used to generate the map. However, I want to avoid having to use omega since it can be slow for larger molecules.

oechem has a function OECanonicalOrderAtoms that is supposed to reorder the atoms, but it doesn't change the indices and the new order is not the same canonical order as the one in omega.
@j-wags, do you have any insight on this?

Ambiguous hydrogen counts

We want to ensure that incoming SMILES have unambiguous protonation / tautomer states.
There are several issues to look out for:

  1. SMILES reader (Openeye or RDKit) preserve the protonation state of input molecule
    This might be an issue for inputs that include geometry and can be resolved with sticking to explicit hydrogen SMILES. choderalab/perses#375
  2. Each SMILES reader is internally consistent with how it assigns hydrogen count for implicit hydrogen SMILES.
    @wiederm has seen cases where this can happen. Explicit hydrogens should also resolve this.
  3. Both SMILES reader in CMILES treat protonation state of the same SMILES consistently.
    This is not always the case. The corner cases I found:

Corner case 1
c-1-c-c-c-c-c-1'

image

Using explicit hydrogen SMILES helps here.
When reading this SMILES, OE adds one H per carbon, RDKit adds 2 H per carbon.

mol = oechem.OEMol()
oechem.OESmilesToMol(mol, 'c-1-c-c-c-c-c-1')

# count implicit hydrogens
imp_h_oe = [atom.GetImplicitHCount() for atom in mol.GetAtoms()]

# RDKit
mol_rd = Chem.MolFromSmiles('c-1-c-c-c-c-c-1')
imp_h_rd = [atom.GetTotalNumHs(False) for atom in mol_rd.GetAtoms()]

print('From implicit H SMILES')
print('oe implicit H: {}'.format(imp_h_oe))
print('rd implicit H: {}'.format(imp_h_rd)) 

# Add explicit H
oechem.OEAddExplicitHydrogens(mol)
new_sm = oechem.OECreateSmiString(mol, oechem.OESMILESFlag_Hydrogens | oechem.OESMILESFlag_ISOMERIC)

mol_oe = oechem.OEMol()
oechem.OESmilesToMol(mol_oe, new_sm)
imp_h_oe = [atom.GetExplicitHCount() for atom in mol.GetAtoms()]
print('From explicit H SMILES')
print('oe from explict h smiles: {}'.format(imp_h_oe))

mol_rd = Chem.MolFromSmiles(new_sm)
imp_h_rd = [atom.GetTotalNumHs(False) for atom in mol_rd.GetAtoms()]
print('rd from explict h smiles: {}'.format(imp_h_rd))

output:

From implicit H SMILES
oe implicit H: [1, 1, 1, 1, 1, 1]
rd implicit H: [2, 2, 2, 2, 2, 2]
From explicit H SMILES
oe from explict h smiles: [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0]
rd from explict h smiles: [1, 1, 1, 1, 1, 1]

Corner case 2
'O1CC2=C(I1C)C=CC=C2'

image
RDKit adds 2 Hs to I
image

Using the same snippet as above, explicit hydrogen SMILES does not resolve the inconsistency. This is probably a bug in RDKit.

Edit: An issue already exists on this rdkit/rdkit#1569. It doesn't look like this will get fixed anytime soon.

From implicit H SMILES
oe implicit H: [0, 2, 0, 0, 0, 3, 1, 1, 1, 1]
rd implicit H: [0, 2, 0, 0, 2, 3, 1, 1, 1, 1]
From explicit H SMILES
oe from explict h smiles: [0, 2, 0, 0, 0, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
rd from explict h smiles: [1, 1, 1, 0, 0, 1, 2, 0, 2, 3]

This issue cannot always be resolved with requiring explicit hydrogen.

Given all these issues, I think it makes sense to require explicit hydrogen SMILES for CMILES.
To check if a SMILES has explicit H, I can check if atom.GetImplicitHCount() > 0 since all implicit H are set to zero when explicit hydrogens are added.

However, there is no equivalent in RDKit that I am aware of. When RDKit reads an explicit hydrogen SMILES, it seems to set all hydrogens to implicit.
@j-wags, how do you check that SMILES have explicit hydrogens for RDKit?

OpenEye toolkits 2020.2.0 changes

CI has been failing for a few days, probably related to a recent OpenEye release. Tests pass with 2020.1.1 but fail with 2020.2.0 (pytest -n auto && pytest -v --lf > file.txt, below):

Here are the release notes; nothing sticks out to me at first pass

============================= test session starts ==============================
platform darwin -- Python 3.8.6, pytest-6.2.1, py-1.10.0, pluggy-0.13.1 -- /Users/mwt/miniconda3/envs/cmiles/bin/python
cachedir: .pytest_cache
rootdir: /Users/mwt/software/cmiles
plugins: cov-2.10.1, xdist-2.2.0, forked-1.3.0
collecting ... collected 12 items
run-last-failure: rerun previous 12 failures (skipped 1 file)

../test_cmiles.py::test_drug_bank_oe[COC(=O)CCC1=C2NC(\\C=C3/N=C(/C=C4\\N\\C(=C/C5=N/C(=C\\2)/C(CCC(O)=O)=C5C)C(C=C)=C4C)C2=CC=C([C@@H](C(=O)OC)[C@@]32C)C(=O)OC)=C1C-[H:54]/[c:1]/1[c:9]/2\\[c:5]([c:6](/[c:10](/[n:44]2[H:93])[c:2](/[c:13]3[n:43]/[c:16]([c:4](\\[c:12]4[c:7]([c:8]([c:11]([n:45]4[H:94])/[c:3]([c:15]/5\\[n:42][c:14]1[C:20](=[C:21]5[C:39]([H:87])([H:88])[C:40]([H:89])([H:90])[C:27](=[O:48])[O:50][H:95])[C:33]([H:70])([H:71])[H:72])/[H:56])[C:38]([H:85])([H:86])[C:41]([H:91])([H:92])[C:28](=[O:49])[O:53][C:37]([H:82])([H:83])[H:84])[C:32]([H:67])([H:68])[H:69])/[H:57])/[C@:30]6([C:19]3=[C:17]([C:18](=[C:22]([C@@:29]6([H:63])[C:26](=[O:47])[O:52][C:36]([H:79])([H:80])[H:81])[C:25](=[O:46])[O:51][C:35]([H:76])([H:77])[H:78])[H:59])[H:58])[C:34]([H:73])([H:74])[H:75])\\[H:55])[C:31]([H:64])([H:65])[H:66])[C:24](=[C:23]([H:60])[H:61])[H:62]] FAILED [  8%]
../test_cmiles.py::test_drug_bank_oe[[H][C@]1(CCC(=O)OC\\C=C(/C)CCC[C@H](C)CCC[C@H](C)CCCC(C)C)[C@H](C)\\C2=C\\C3=C(C)C(C(C)=O)=C4\\C=C5/N=C(/C=C6\\N([Mg]N34)C3=C([C@@H](C(=O)OC)C(=O)C3=C6C)C1=N2)[C@H](CC)[C@H]5C-[H:67]/[c:1]1/[c:9]2[c:5]([c:8]([c:11]/3[n:58]2[Mg:66][n:59]4/[c:10]([c:2](\\[c:14]5[n:56]\\[c:13]1\\[C@:24]([C@@:26]5([H:74])[C:43]([H:118])([H:119])[C:34]([H:94])([H:95])[H:96])([H:72])[C:32]([H:88])([H:89])[H:90])/[H:68])/[c:7]([c:4]6[c:12]4[c:6]([c:16]7[n:57]/[c:15]([c:3]3/[H:69])/[C@@:25]([C@:27]7([H:75])[C:44]([H:120])([H:121])[C:42]([H:116])([H:117])[C:22](=[O:63])[O:65][C:40]([H:112])([H:113])/[C:18](=[C:20](\\[C:31]([H:85])([H:86])[H:87])/[C:41]([H:114])([H:115])[C:45]([H:122])([H:123])[C:48]([H:128])([H:129])[C@:54]([H:139])([C:37]([H:103])([H:104])[H:105])[C:51]([H:134])([H:135])[C:47]([H:126])([H:127])[C:52]([H:136])([H:137])[C@:55]([H:140])([C:38]([H:106])([H:107])[H:108])[C:50]([H:132])([H:133])[C:46]([H:124])([H:125])[C:49]([H:130])([H:131])[C:53]([H:138])([C:35]([H:97])([H:98])[H:99])[C:36]([H:100])([H:101])[H:102])/[H:70])([H:73])[C:33]([H:91])([H:92])[H:93])[C@@:23]([C:17]6=[O:60])([H:71])[C:21](=[O:62])[O:64][C:39]([H:109])([H:110])[H:111])[C:28]([H:76])([H:77])[H:78])[C:29]([H:79])([H:80])[H:81])[C:19](=[O:61])[C:30]([H:82])([H:83])[H:84]] FAILED [ 16%]
../test_cmiles.py::test_drug_bank_oe[CCC1=C(C)\\C2=C\\C3=C(C=C)C(C)=C4\\C=C5/N=C([C@@H](CCC(=O)OC\\C=C(/C)CCC[C@H](C)CCC[C@H](C)CCCC(C)C)[C@@H]5C)C5=C6N([Mg]N34)\\C(=C/C1=N2)C(C)=C6C(=O)[C@@H]5C(=O)OC-[H:66]/[c:1]1/[c:9]2[c:5]([c:8]([c:11]/3[n:58]2[Mg:65][n:59]4/[c:10]([c:2](\\[c:14]5[n:56]\\[c:13]1\\[C:18](=[C:19]5[C:40]([H:109])([H:110])[C:34]([H:91])([H:92])[H:93])[C:31]([H:82])([H:83])[H:84])/[H:67])/[c:7]([c:4]6[c:12]4[c:6]([c:16]7[n:57]/[c:15]([c:3]3/[H:68])/[C@@:27]([C@:28]7([H:75])[C:44]([H:117])([H:118])[C:43]([H:115])([H:116])[C:25](=[O:62])[O:64][C:41]([H:111])([H:112])/[C:22](=[C:23](\\[C:32]([H:85])([H:86])[H:87])/[C:42]([H:113])([H:114])[C:45]([H:119])([H:120])[C:48]([H:125])([H:126])[C@:54]([H:136])([C:37]([H:100])([H:101])[H:102])[C:51]([H:131])([H:132])[C:47]([H:123])([H:124])[C:52]([H:133])([H:134])[C@:55]([H:137])([C:38]([H:103])([H:104])[H:105])[C:50]([H:129])([H:130])[C:46]([H:121])([H:122])[C:49]([H:127])([H:128])[C:53]([H:135])([C:35]([H:94])([H:95])[H:96])[C:36]([H:97])([H:98])[H:99])/[H:72])([H:74])[C:33]([H:88])([H:89])[H:90])[C@@:26]([C:17]6=[O:60])([H:73])[C:24](=[O:61])[O:63][C:39]([H:106])([H:107])[H:108])[C:29]([H:76])([H:77])[H:78])[C:30]([H:79])([H:80])[H:81])[C:21](=[C:20]([H:69])[H:70])[H:71]] FAILED [ 25%]
../test_cmiles.py::test_drug_bank_oe[[Co+7].[H]\\C-1=C2\\[N-]\\C(=C([H])/C3=N/C(=C([H])\\C4=C(CCC([O-])=O)C(C)=C(N4)\\C([H])=C4\\C=C(C)C-1=N4)/C(CCC(O)=O)=C3C)C(C)=C2-[H:40][c:1]\\1[c:6](/[c:10]/2[c:3](/[c:14]3[n:33]/[c:16]([c:5](\\[c:12]4[c:8]([c:7]([c:11]([n:34]4[H:66])/[c:4]([c:15]/5\\[n:32][c:13](/[c:2]([c:9]1\\[n-:31]2)/[H:41])[C:18](=[C:17]5[H:45])[C:25]([H:52])([H:53])[H:54])/[H:43])[C:24]([H:49])([H:50])[H:51])[C:27]([H:58])([H:59])[C:29]([H:62])([H:63])[C:21](=[O:36])[O-:35])/[H:44])/[C:20](=[C:19]3[C:26]([H:55])([H:56])[H:57])[C:28]([H:60])([H:61])[C:30]([H:64])([H:65])[C:22](=[O:37])[O:38][H:67])\\[H:42])[C:23]([H:46])([H:47])[H:48].[Co+7:39]] FAILED [ 33%]
../test_cmiles.py::test_drug_bank_oe[CC1=C(CCC(O)=O)/C2=C/C3=N/C(=C\\C4=C(C)C(C=C)=C(N4)/C=C4\\N=C(\\C=C\\1/N\\2)C(C=C)=C4C)/C(C)=C3CCC(O)=O-[H:43]/[c:1]1/[c:9]2[c:5]([c:6]([c:10]([n:37]2[H:73])/[c:2]([c:15]/3\\[n:36][c:16](/[c:4]([c:12]\\4/[c:8]([c:7](/[c:11](/[n:38]4[H:74])[c:3](/[c:13]5[n:35]\\[c:14]1\\[C:18](=[C:17]5[C:24](=[C:22]([H:49])[H:50])[H:52])[C:29]([H:59])([H:60])[H:61])\\[H:45])[C:28]([H:56])([H:57])[H:58])[C:31]([H:65])([H:66])[C:33]([H:69])([H:70])[C:25](=[O:39])[O:41][H:75])/[H:46])[C:20](=[C:19]3[C:30]([H:62])([H:63])[H:64])[C:32]([H:67])([H:68])[C:34]([H:71])([H:72])[C:26](=[O:40])[O:42][H:76])/[H:44])[C:27]([H:53])([H:54])[H:55])[C:23](=[C:21]([H:47])[H:48])[H:51]] FAILED [ 41%]
../test_cmiles.py::test_drug_bank_oe[CC1=C(CCC(O)=O)/C2=C/C3=N/C(=C\\C4=C(C)C(CCC(O)=O)=C(N4)/C=C4\\N=C(\\C=C\\1/N\\2)C(CCC(O)=O)=C4C)/C(CCC(O)=O)=C3C-[H:49]/[c:1]1/[c:9]2[c:5]([c:7]([c:11]([n:39]2[H:81])/[c:3]([c:16]/3\\[n:38][c:14](/[c:2]([c:10]\\4/[c:6]([c:8](/[c:12](/[n:40]4[H:82])[c:4](/[c:15]5[n:37]\\[c:13]1\\[C:19](=[C:17]5[C:27]([H:59])([H:60])[H:61])[C:31]([H:69])([H:70])[C:35]([H:77])([H:78])[C:23](=[O:43])[O:47][H:85])\\[H:52])[C:30]([H:67])([H:68])[C:34]([H:75])([H:76])[C:22](=[O:42])[O:46][H:84])[C:26]([H:56])([H:57])[H:58])/[H:50])[C:20](=[C:18]3[C:28]([H:62])([H:63])[H:64])[C:32]([H:71])([H:72])[C:36]([H:79])([H:80])[C:24](=[O:44])[O:48][H:86])/[H:51])[C:29]([H:65])([H:66])[C:33]([H:73])([H:74])[C:21](=[O:41])[O:45][H:83])[C:25]([H:53])([H:54])[H:55]] FAILED [ 50%]
../test_cmiles.py::test_drug_bank_oe[[Mg++].CCC1=C(C=O)C2=N\\C\\1=C/C1=C(C)C3=C([N-]1)\\C([C@@H](C(=O)OC)C3=O)=C1/N=C(/C=C3\\[N-]/C(=C\\2)C(C=C)=C3C)[C@@H](C)[C@@H]1CCC(=O)OC\\C=C(/C)CCC[C@H](C)CCC[C@H](C)CCCC(C)C-[H:67]/[c:1]/1[c:9]/2\\[c:5]([c:8](/[c:11](/[n-:56]2)[c:3](/[c:15]3[n:59]/[c:16]([c:6]/4\\[c:12]5[c:4]([c:7]([c:10]([n-:57]5)/[c:2]([c:14]/6\\[n:58][c:13]1[C:18](=[C:19]6[C:40]([H:108])([H:109])[C:34]([H:90])([H:91])[H:92])[C:22](=[O:61])[H:73])/[H:68])[C:30]([H:78])([H:79])[H:80])[C:17](=[O:60])[C@:27]4([H:75])[C:25](=[O:62])[O:64][C:39]([H:105])([H:106])[H:107])/[C@@:29]([C@:28]3([H:76])[C:33]([H:87])([H:88])[H:89])([H:77])[C:44]([H:116])([H:117])[C:43]([H:114])([H:115])[C:26](=[O:63])[O:65][C:41]([H:110])([H:111])/[C:23](=[C:24](\\[C:32]([H:84])([H:85])[H:86])/[C:42]([H:112])([H:113])[C:45]([H:118])([H:119])[C:48]([H:124])([H:125])[C@:54]([H:135])([C:37]([H:99])([H:100])[H:101])[C:51]([H:130])([H:131])[C:47]([H:122])([H:123])[C:52]([H:132])([H:133])[C@:55]([H:136])([C:38]([H:102])([H:103])[H:104])[C:50]([H:128])([H:129])[C:46]([H:120])([H:121])[C:49]([H:126])([H:127])[C:53]([H:134])([C:35]([H:93])([H:94])[H:95])[C:36]([H:96])([H:97])[H:98])/[H:74])\\[H:69])[C:31]([H:81])([H:82])[H:83])[C:21](=[C:20]([H:70])[H:71])[H:72].[Mg+2:66]] FAILED [ 58%]
../test_cmiles.py::test_drug_bank_oe[[Cl-].[Cl-].[Sn+4].CCC1=C2[N-]C(\\C=C3/N=C(/C=C4\\[N-]\\C(=C/C5=N/C(=C\\2)/C(C)=C5CC)C(C)=C4CCC(O)=O)C(CCC(O)=O)=C3C)=C1C-[H:46]/[c:1]1/[c:9]2[c:5]([c:7]([c:11]([n-:35]2)/[c:3]([c:15]/3\\[n:38][c:14](/[c:2]([c:10]\\4/[c:6]([c:8](/[c:12](/[n-:36]4)[c:4](/[c:16]5[n:37]\\[c:13]1\\[C:17](=[C:20]5[C:32]([H:74])([H:75])[C:34]([H:78])([H:79])[C:22](=[O:40])[O:42][H:81])[C:25]([H:56])([H:57])[H:58])\\[H:49])[C:30]([H:70])([H:71])[C:33]([H:76])([H:77])[C:21](=[O:39])[O:41][H:80])[C:24]([H:53])([H:54])[H:55])/[H:47])[C:19](=[C:18]3[C:26]([H:59])([H:60])[H:61])[C:31]([H:72])([H:73])[C:28]([H:65])([H:66])[H:67])/[H:48])[C:29]([H:68])([H:69])[C:27]([H:62])([H:63])[H:64])[C:23]([H:50])([H:51])[H:52].[Cl-:43].[Cl-:44].[Sn+4:45]] FAILED [ 66%]
../test_cmiles.py::test_drug_bank_oe[O.[Lu+3].CC([O-])=O.CC([O-])=O.[H]/C1=C2/N=C(/C(/[H])=C3\\[N-]/C(=C([H])\\C4=N\\C(=C(/[H])\\N=C5\\C=C(OCCOCCOCCOC)C(OCCOCCOCCOC)=C\\C\\5=N\\1)\\C(C)=C4CCCO)C(CC)=C3CC)C(CCCO)=C2C-[H:75]/[c:2]/1[c:10]/2\\[c:8]([c:7](/[c:9](/[n-:53]2)[c:1](/[c:15]3[n:56]/[c:17]([c:5](\\[n:54][c:11]/4\\[c:3]([c:13]([c:14]([c:4](\\[c:12]4[n:55]\\[c:6]([c:18]/5\\[n:57][c:16]1[C:20](=[C:22]5[C:26]([H:83])([H:84])[H:85])[C:36]([H:110])([H:111])[C:38]([H:114])([H:115])[C:40]([H:118])([H:119])[O:64][H:147])\\[H:79])[H:77])[O:66][C:42]([H:122])([H:123])[C:46]([H:130])([H:131])[O:70][C:50]([H:138])([H:139])[C:52]([H:142])([H:143])[O:72][C:48]([H:134])([H:135])[C:44]([H:126])([H:127])[O:68][C:32]([H:101])([H:102])[H:103])[O:65][C:41]([H:120])([H:121])[C:45]([H:128])([H:129])[O:69][C:49]([H:136])([H:137])[C:51]([H:140])([H:141])[O:71][C:47]([H:132])([H:133])[C:43]([H:124])([H:125])[O:67][C:31]([H:98])([H:99])[H:100])[H:76])/[H:78])/[C:21](=[C:19]3[C:35]([H:108])([H:109])[C:37]([H:112])([H:113])[C:39]([H:116])([H:117])[O:63][H:146])[C:25]([H:80])([H:81])[H:82])\\[H:74])[C:33]([H:104])([H:105])[C:29]([H:92])([H:93])[H:94])[C:34]([H:106])([H:107])[C:30]([H:95])([H:96])[H:97].[H:86][C:27]([H:87])([H:88])[C:23](=[O:60])[O-:58].[H:89][C:28]([H:90])([H:91])[C:24](=[O:61])[O-:59].[H:144][O:62][H:145].[Lu+3:73]] FAILED [ 75%]
../test_cmiles.py::test_drug_bank_oe[[Gd+3].CC([O-])=O.CC([O-])=O.CCC1=C(CC)/C2=C/C3=N/C(=C\\N=C4/C=C(OCCOCCOCCOC)C(OCCOCCOCCOC)=C/C/4=N\\C=C4/N=C(/C=C\\1\\[N-]\\2)C(CCCO)=C4C)/C(C)=C3CCCO-[H:73]/[c:1]1/[c:15]2[n:56]/[c:17]([c:5](\\[n:54][c:11]/3\\[c:12]([n:55]\\[c:6]([c:18]\\4/[n:57][c:16](/[c:2]([c:10]/5\\[n-:53]\\[c:9]1\\[c:7]([c:8]5[C:34]([C:30]([H:94])([H:95])[H:96])([H:105])[H:106])[C:33]([C:29]([H:91])([H:92])[H:93])([H:103])[H:104])/[H:74])[C:20](=[C:22]4[C:26]([H:82])([H:83])[H:84])[C:36]([C:38]([C:40]([O:63][H:144])([H:117])[H:118])([H:113])[H:114])([H:109])[H:110])\\[H:78])\\[c:4]([c:14]([c:13]([c:3]3[H:75])[O:64][C:41]([C:45]([O:68][C:49]([C:51]([O:70][C:47]([C:43]([O:66][C:31]([H:97])([H:98])[H:99])([H:123])[H:124])([H:131])[H:132])([H:139])[H:140])([H:135])[H:136])([H:127])[H:128])([H:119])[H:120])[O:65][C:42]([C:46]([O:69][C:50]([C:52]([O:71][C:48]([C:44]([O:67][C:32]([H:100])([H:101])[H:102])([H:125])[H:126])([H:133])[H:134])([H:141])[H:142])([H:137])[H:138])([H:129])[H:130])([H:121])[H:122])[H:76])/[H:77])/[C:21](=[C:19]2[C:35]([C:37]([C:39]([O:62][H:143])([H:115])[H:116])([H:111])[H:112])([H:107])[H:108])[C:25]([H:79])([H:80])[H:81].[H:85][C:27]([C:23](=[O:60])[O-:58])([H:86])[H:87].[H:88][C:28]([C:24](=[O:61])[O-:59])([H:89])[H:90].[Gd+3:72]] FAILED [ 83%]
../test_cmiles.py::test_drug_bank_oe[CCC1=C(C)\\C2=C\\C3=C(C=C)C(C)=C(N3)\\C=C3/N=C([C@@H](CCC(O)=O)[C@@H]3C)/C(/CC(=O)N[C@@H](CC(O)=O)C(O)=O)=C3\\N\\C(=C/C1=N2)C(C)=C3C(O)=O-[H:53]/[c:1]1/[c:9]2[c:4]([c:6]([c:11]([n:41]2[H:87])/[c:3]([c:15]/3\\[n:40][c:16](/[c:8]([c:12]\\4/[c:5]([c:7](/[c:10](/[n:42]4[H:88])[c:2](/[c:14]5[n:39]\\[c:13]1\\[C:17](=[C:18]5[C:34]([H:78])([H:79])[C:32]([H:73])([H:74])[H:75])[C:30]([H:67])([H:68])[H:69])\\[H:54])[C:29]([H:64])([H:65])[H:66])[C:21](=[O:44])[O:49][H:90])/[C:33]([H:76])([H:77])[C:22](=[O:45])[N:43]([H:89])[C@:38]([H:86])([C:25](=[O:48])[O:52][H:93])[C:36]([H:82])([H:83])[C:24](=[O:47])[O:51][H:92])[C@@:27]([C@:26]3([H:59])[C:31]([H:70])([H:71])[H:72])([H:60])[C:37]([H:84])([H:85])[C:35]([H:80])([H:81])[C:23](=[O:46])[O:50][H:91])/[H:55])[C:28]([H:61])([H:62])[H:63])[C:20](=[C:19]([H:56])[H:57])[H:58]] FAILED [ 91%]
../test_cmiles.py::test_drug_bank_oe[N1C2=C3C=CC=CC3=C1\\N=C1/N=C(/N=C3\\N=C(NC4=N\\C(=N/2)C2=CC=CC=C42)C2=CC=CC=C32)C2=CC=CC=C12-[H:41][c:1]1[c:2]([c:10]([c:18]2[c:17]([c:9]1[H:49])[c:25]3/[n:33][c:27]/4\\[n:35][c:29](/[n:36][c:30]/5\\[n:38][c:32]([n:40]([c:31]-6[n:37]/[c:28]([n:34]\\[c:26]2[n:39]3[H:57])/[c:21]7[c:23]6[c:15]([c:7]([c:5]([c:13]7[H:53])[H:45])[H:47])[H:55])[H:58])-[c:24]8[c:22]5[c:14]([c:6]([c:8]([c:16]8[H:56])[H:48])[H:46])[H:54])-[c:20]9[c:19]4[c:11]([c:3]([c:4]([c:12]9[H:52])[H:44])[H:43])[H:51])[H:50])[H:42]] FAILED [100%]

=================================== FAILURES ===================================
_ test_drug_bank_oe[COC(=O)CCC1=C2NC(\\C=C3/N=C(/C=C4\\N\\C(=C/C5=N/C(=C\\2)/C(CCC(O)=O)=C5C)C(C=C)=C4C)C2=CC=C([C@@H](C(=O)OC)[C@@]32C)C(=O)OC)=C1C-[H:54]/[c:1]/1[c:9]/2\\[c:5]([c:6](/[c:10](/[n:44]2[H:93])[c:2](/[c:13]3[n:43]/[c:16]([c:4](\\[c:12]4[c:7]([c:8]([c:11]([n:45]4[H:94])/[c:3]([c:15]/5\\[n:42][c:14]1[C:20](=[C:21]5[C:39]([H:87])([H:88])[C:40]([H:89])([H:90])[C:27](=[O:48])[O:50][H:95])[C:33]([H:70])([H:71])[H:72])/[H:56])[C:38]([H:85])([H:86])[C:41]([H:91])([H:92])[C:28](=[O:49])[O:53][C:37]([H:82])([H:83])[H:84])[C:32]([H:67])([H:68])[H:69])/[H:57])/[C@:30]6([C:19]3=[C:17]([C:18](=[C:22]([C@@:29]6([H:63])[C:26](=[O:47])[O:52][C:36]([H:79])([H:80])[H:81])[C:25](=[O:46])[O:51][C:35]([H:76])([H:77])[H:78])[H:59])[H:58])[C:34]([H:73])([H:74])[H:75])\\[H:55])[C:31]([H:64])([H:65])[H:66])[C:24](=[C:23]([H:60])[H:61])[H:62]] _

input = 'COC(=O)CCC1=C2NC(\\C=C3/N=C(/C=C4\\N\\C(=C/C5=N/C(=C\\2)/C(CCC(O)=O)=C5C)C(C=C)=C4C)C2=CC=C([C@@H](C(=O)OC)[C@@]32C)C(=O)OC)=C1C'
output = '[H:54]/[c:1]/1[c:9]/2\\[c:5]([c:6](/[c:10](/[n:44]2[H:93])[c:2](/[c:13]3[n:43]/[c:16]([c:4](\\[c:12]4[c:7]([c:8]([c:1...])[H:59])[H:58])[C:34]([H:73])([H:74])[H:75])\\[H:55])[C:31]([H:64])([H:65])[H:66])[C:24](=[C:23]([H:60])[H:61])[H:62]'

    @using_openeye
    @pytest.mark.parametrize("input, output", get_smiles_lists(get_fn('drug_bank_stereo.smi'), get_fn('drug_bank_mapped_smi_oe.smi')))
    def test_drug_bank_oe(input, output):
        """
    
        Parameters
        ----------
        input
        output
    
        Returns
        -------
    
        """
        mol = oechem.OEMol()
        oechem.OEParseSmiles(mol, input)
>       assert cmiles.utils.mol_to_smiles(mol, mapped=True, isomeric=True, explicit_hydrogen=True) == output
E       AssertionError: assert '[H:54][c:1]1...[H:61])[H:62]' == '[H:54]/[c:1]...[H:61])[H:62]'
E         - [H:54]/[c:1]/1[c:9]/2\[c:5]([c:6](/[c:10](/[n:44]2[H:93])[c:2](/[c:13]3[n:43]/[c:16]([c:4](\[c:12]4[c:7]([c:8]([c:11]([n:45]4[H:94])/[c:3]([c:15]/5\[n:42][c:14]1[C:20](=[C:21]5[C:39]([H:87])([H:88])[C:40]([H:89])([H:90])[C:27](=[O:48])[O:50][H:95])[C:33]([H:70])([H:71])[H:72])/[H:56])[C:38]([H:85])([H:86])[C:41]([H:91])([H:92])[C:28](=[O:49])[O:53][C:37]([H:82])([H:83])[H:84])[C:32]([H:67])([H:68])[H:69])/[H:57])/[C@:30]6([C:19]3=[C:17]([C:18](=[C:22]([C@@:29]6([H:63])[C:26](=[O:47])[O:52][C:36]([H:79])([H:80])[H:81])[C:25](=[O:46])[O:51][C:35]([H:76])([H:77])[H:78])[...
E         
E         ...Full output truncated (2 lines hidden), use '-vv' to show

../test_cmiles.py:318: AssertionError
_ test_drug_bank_oe[[H][C@]1(CCC(=O)OC\\C=C(/C)CCC[C@H](C)CCC[C@H](C)CCCC(C)C)[C@H](C)\\C2=C\\C3=C(C)C(C(C)=O)=C4\\C=C5/N=C(/C=C6\\N([Mg]N34)C3=C([C@@H](C(=O)OC)C(=O)C3=C6C)C1=N2)[C@H](CC)[C@H]5C-[H:67]/[c:1]1/[c:9]2[c:5]([c:8]([c:11]/3[n:58]2[Mg:66][n:59]4/[c:10]([c:2](\\[c:14]5[n:56]\\[c:13]1\\[C@:24]([C@@:26]5([H:74])[C:43]([H:118])([H:119])[C:34]([H:94])([H:95])[H:96])([H:72])[C:32]([H:88])([H:89])[H:90])/[H:68])/[c:7]([c:4]6[c:12]4[c:6]([c:16]7[n:57]/[c:15]([c:3]3/[H:69])/[C@@:25]([C@:27]7([H:75])[C:44]([H:120])([H:121])[C:42]([H:116])([H:117])[C:22](=[O:63])[O:65][C:40]([H:112])([H:113])/[C:18](=[C:20](\\[C:31]([H:85])([H:86])[H:87])/[C:41]([H:114])([H:115])[C:45]([H:122])([H:123])[C:48]([H:128])([H:129])[C@:54]([H:139])([C:37]([H:103])([H:104])[H:105])[C:51]([H:134])([H:135])[C:47]([H:126])([H:127])[C:52]([H:136])([H:137])[C@:55]([H:140])([C:38]([H:106])([H:107])[H:108])[C:50]([H:132])([H:133])[C:46]([H:124])([H:125])[C:49]([H:130])([H:131])[C:53]([H:138])([C:35]([H:97])([H:98])[H:99])[C:36]([H:100])([H:101])[H:102])/[H:70])([H:73])[C:33]([H:91])([H:92])[H:93])[C@@:23]([C:17]6=[O:60])([H:71])[C:21](=[O:62])[O:64][C:39]([H:109])([H:110])[H:111])[C:28]([H:76])([H:77])[H:78])[C:29]([H:79])([H:80])[H:81])[C:19](=[O:61])[C:30]([H:82])([H:83])[H:84]] _

input = '[H][C@]1(CCC(=O)OC\\C=C(/C)CCC[C@H](C)CCC[C@H](C)CCCC(C)C)[C@H](C)\\C2=C\\C3=C(C)C(C(C)=O)=C4\\C=C5/N=C(/C=C6\\N([Mg]N34)C3=C([C@@H](C(=O)OC)C(=O)C3=C6C)C1=N2)[C@H](CC)[C@H]5C'
output = '[H:67]/[c:1]1/[c:9]2[c:5]([c:8]([c:11]/3[n:58]2[Mg:66][n:59]4/[c:10]([c:2](\\[c:14]5[n:56]\\[c:13]1\\[C@:24]([C@@:26]...([H:110])[H:111])[C:28]([H:76])([H:77])[H:78])[C:29]([H:79])([H:80])[H:81])[C:19](=[O:61])[C:30]([H:82])([H:83])[H:84]'

    @using_openeye
    @pytest.mark.parametrize("input, output", get_smiles_lists(get_fn('drug_bank_stereo.smi'), get_fn('drug_bank_mapped_smi_oe.smi')))
    def test_drug_bank_oe(input, output):
        """
    
        Parameters
        ----------
        input
        output
    
        Returns
        -------
    
        """
        mol = oechem.OEMol()
        oechem.OEParseSmiles(mol, input)
>       assert cmiles.utils.mol_to_smiles(mol, mapped=True, isomeric=True, explicit_hydrogen=True) == output
E       AssertionError: assert '[H:67][c:1]1...[H:83])[H:84]' == '[H:67]/[c:1]...[H:83])[H:84]'
E         - [H:67]/[c:1]1/[c:9]2[c:5]([c:8]([c:11]/3[n:58]2[Mg:66][n:59]4/[c:10]([c:2](\[c:14]5[n:56]\[c:13]1\[C@:24]([C@@:26]5([H:74])[C:43]([H:118])([H:119])[C:34]([H:94])([H:95])[H:96])([H:72])[C:32]([H:88])([H:89])[H:90])/[H:68])/[c:7]([c:4]6[c:12]4[c:6]([c:16]7[n:57]/[c:15]([c:3]3/[H:69])/[C@@:25]([C@:27]7([H:75])[C:44]([H:120])([H:121])[C:42]([H:116])([H:117])[C:22](=[O:63])[O:65][C:40]([H:112])([H:113])/[C:18](=[C:20](\[C:31]([H:85])([H:86])[H:87])/[C:41]([H:114])([H:115])[C:45]([H:122])([H:123])[C:48]([H:128])([H:129])[C@:54]([H:139])([C:37]([H:103])([H:104])[H:105])[C:51...
E         
E         ...Full output truncated (4 lines hidden), use '-vv' to show

../test_cmiles.py:318: AssertionError
_ test_drug_bank_oe[CCC1=C(C)\\C2=C\\C3=C(C=C)C(C)=C4\\C=C5/N=C([C@@H](CCC(=O)OC\\C=C(/C)CCC[C@H](C)CCC[C@H](C)CCCC(C)C)[C@@H]5C)C5=C6N([Mg]N34)\\C(=C/C1=N2)C(C)=C6C(=O)[C@@H]5C(=O)OC-[H:66]/[c:1]1/[c:9]2[c:5]([c:8]([c:11]/3[n:58]2[Mg:65][n:59]4/[c:10]([c:2](\\[c:14]5[n:56]\\[c:13]1\\[C:18](=[C:19]5[C:40]([H:109])([H:110])[C:34]([H:91])([H:92])[H:93])[C:31]([H:82])([H:83])[H:84])/[H:67])/[c:7]([c:4]6[c:12]4[c:6]([c:16]7[n:57]/[c:15]([c:3]3/[H:68])/[C@@:27]([C@:28]7([H:75])[C:44]([H:117])([H:118])[C:43]([H:115])([H:116])[C:25](=[O:62])[O:64][C:41]([H:111])([H:112])/[C:22](=[C:23](\\[C:32]([H:85])([H:86])[H:87])/[C:42]([H:113])([H:114])[C:45]([H:119])([H:120])[C:48]([H:125])([H:126])[C@:54]([H:136])([C:37]([H:100])([H:101])[H:102])[C:51]([H:131])([H:132])[C:47]([H:123])([H:124])[C:52]([H:133])([H:134])[C@:55]([H:137])([C:38]([H:103])([H:104])[H:105])[C:50]([H:129])([H:130])[C:46]([H:121])([H:122])[C:49]([H:127])([H:128])[C:53]([H:135])([C:35]([H:94])([H:95])[H:96])[C:36]([H:97])([H:98])[H:99])/[H:72])([H:74])[C:33]([H:88])([H:89])[H:90])[C@@:26]([C:17]6=[O:60])([H:73])[C:24](=[O:61])[O:63][C:39]([H:106])([H:107])[H:108])[C:29]([H:76])([H:77])[H:78])[C:30]([H:79])([H:80])[H:81])[C:21](=[C:20]([H:69])[H:70])[H:71]] _

input = 'CCC1=C(C)\\C2=C\\C3=C(C=C)C(C)=C4\\C=C5/N=C([C@@H](CCC(=O)OC\\C=C(/C)CCC[C@H](C)CCC[C@H](C)CCCC(C)C)[C@@H]5C)C5=C6N([Mg]N34)\\C(=C/C1=N2)C(C)=C6C(=O)[C@@H]5C(=O)OC'
output = '[H:66]/[c:1]1/[c:9]2[c:5]([c:8]([c:11]/3[n:58]2[Mg:65][n:59]4/[c:10]([c:2](\\[c:14]5[n:56]\\[c:13]1\\[C:18](=[C:19]5[...[H:106])([H:107])[H:108])[C:29]([H:76])([H:77])[H:78])[C:30]([H:79])([H:80])[H:81])[C:21](=[C:20]([H:69])[H:70])[H:71]'

    @using_openeye
    @pytest.mark.parametrize("input, output", get_smiles_lists(get_fn('drug_bank_stereo.smi'), get_fn('drug_bank_mapped_smi_oe.smi')))
    def test_drug_bank_oe(input, output):
        """
    
        Parameters
        ----------
        input
        output
    
        Returns
        -------
    
        """
        mol = oechem.OEMol()
        oechem.OEParseSmiles(mol, input)
>       assert cmiles.utils.mol_to_smiles(mol, mapped=True, isomeric=True, explicit_hydrogen=True) == output
E       AssertionError: assert '[H:66][c:1]1...[H:70])[H:71]' == '[H:66]/[c:1]...[H:70])[H:71]'
E         - [H:66]/[c:1]1/[c:9]2[c:5]([c:8]([c:11]/3[n:58]2[Mg:65][n:59]4/[c:10]([c:2](\[c:14]5[n:56]\[c:13]1\[C:18](=[C:19]5[C:40]([H:109])([H:110])[C:34]([H:91])([H:92])[H:93])[C:31]([H:82])([H:83])[H:84])/[H:67])/[c:7]([c:4]6[c:12]4[c:6]([c:16]7[n:57]/[c:15]([c:3]3/[H:68])/[C@@:27]([C@:28]7([H:75])[C:44]([H:117])([H:118])[C:43]([H:115])([H:116])[C:25](=[O:62])[O:64][C:41]([H:111])([H:112])/[C:22](=[C:23](\[C:32]([H:85])([H:86])[H:87])/[C:42]([H:113])([H:114])[C:45]([H:119])([H:120])[C:48]([H:125])([H:126])[C@:54]([H:136])([C:37]([H:100])([H:101])[H:102])[C:51]([H:131])([H:132]...
E         
E         ...Full output truncated (4 lines hidden), use '-vv' to show

../test_cmiles.py:318: AssertionError
_ test_drug_bank_oe[[Co+7].[H]\\C-1=C2\\[N-]\\C(=C([H])/C3=N/C(=C([H])\\C4=C(CCC([O-])=O)C(C)=C(N4)\\C([H])=C4\\C=C(C)C-1=N4)/C(CCC(O)=O)=C3C)C(C)=C2-[H:40][c:1]\\1[c:6](/[c:10]/2[c:3](/[c:14]3[n:33]/[c:16]([c:5](\\[c:12]4[c:8]([c:7]([c:11]([n:34]4[H:66])/[c:4]([c:15]/5\\[n:32][c:13](/[c:2]([c:9]1\\[n-:31]2)/[H:41])[C:18](=[C:17]5[H:45])[C:25]([H:52])([H:53])[H:54])/[H:43])[C:24]([H:49])([H:50])[H:51])[C:27]([H:58])([H:59])[C:29]([H:62])([H:63])[C:21](=[O:36])[O-:35])/[H:44])/[C:20](=[C:19]3[C:26]([H:55])([H:56])[H:57])[C:28]([H:60])([H:61])[C:30]([H:64])([H:65])[C:22](=[O:37])[O:38][H:67])\\[H:42])[C:23]([H:46])([H:47])[H:48].[Co+7:39]] _

input = '[Co+7].[H]\\C-1=C2\\[N-]\\C(=C([H])/C3=N/C(=C([H])\\C4=C(CCC([O-])=O)C(C)=C(N4)\\C([H])=C4\\C=C(C)C-1=N4)/C(CCC(O)=O)=C3C)C(C)=C2'
output = '[H:40][c:1]\\1[c:6](/[c:10]/2[c:3](/[c:14]3[n:33]/[c:16]([c:5](\\[c:12]4[c:8]([c:7]([c:11]([n:34]4[H:66])/[c:4]([c:15...C:28]([H:60])([H:61])[C:30]([H:64])([H:65])[C:22](=[O:37])[O:38][H:67])\\[H:42])[C:23]([H:46])([H:47])[H:48].[Co+7:39]'

    @using_openeye
    @pytest.mark.parametrize("input, output", get_smiles_lists(get_fn('drug_bank_stereo.smi'), get_fn('drug_bank_mapped_smi_oe.smi')))
    def test_drug_bank_oe(input, output):
        """
    
        Parameters
        ----------
        input
        output
    
        Returns
        -------
    
        """
        mol = oechem.OEMol()
        oechem.OEParseSmiles(mol, input)
>       assert cmiles.utils.mol_to_smiles(mol, mapped=True, isomeric=True, explicit_hydrogen=True) == output
E       AssertionError: assert '[H:40][c:1]1...48].[Co+7:39]' == '[H:40][c:1]\...48].[Co+7:39]'
E         - [H:40][c:1]\1[c:6](/[c:10]/2[c:3](/[c:14]3[n:33]/[c:16]([c:5](\[c:12]4[c:8]([c:7]([c:11]([n:34]4[H:66])/[c:4]([c:15]/5\[n:32][c:13](/[c:2]([c:9]1\[n-:31]2)/[H:41])[C:18](=[C:17]5[H:45])[C:25]([H:52])([H:53])[H:54])/[H:43])[C:24]([H:49])([H:50])[H:51])[C:27]([H:58])([H:59])[C:29]([H:62])([H:63])[C:21](=[O:36])[O-:35])/[H:44])/[C:20](=[C:19]3[C:26]([H:55])([H:56])[H:57])[C:28]([H:60])([H:61])[C:30]([H:64])([H:65])[C:22](=[O:37])[O:38][H:67])\[H:42])[C:23]([H:46])([H:47])[H:48].[Co+7:39]
E         ?            ^^^^^^^^^^^^^^^^^^^^^^^^             ^^^^^^^^^^^^^^^                    ...
E         
E         ...Full output truncated (3 lines hidden), use '-vv' to show

../test_cmiles.py:318: AssertionError
_ test_drug_bank_oe[CC1=C(CCC(O)=O)/C2=C/C3=N/C(=C\\C4=C(C)C(C=C)=C(N4)/C=C4\\N=C(\\C=C\\1/N\\2)C(C=C)=C4C)/C(C)=C3CCC(O)=O-[H:43]/[c:1]1/[c:9]2[c:5]([c:6]([c:10]([n:37]2[H:73])/[c:2]([c:15]/3\\[n:36][c:16](/[c:4]([c:12]\\4/[c:8]([c:7](/[c:11](/[n:38]4[H:74])[c:3](/[c:13]5[n:35]\\[c:14]1\\[C:18](=[C:17]5[C:24](=[C:22]([H:49])[H:50])[H:52])[C:29]([H:59])([H:60])[H:61])\\[H:45])[C:28]([H:56])([H:57])[H:58])[C:31]([H:65])([H:66])[C:33]([H:69])([H:70])[C:25](=[O:39])[O:41][H:75])/[H:46])[C:20](=[C:19]3[C:30]([H:62])([H:63])[H:64])[C:32]([H:67])([H:68])[C:34]([H:71])([H:72])[C:26](=[O:40])[O:42][H:76])/[H:44])[C:27]([H:53])([H:54])[H:55])[C:23](=[C:21]([H:47])[H:48])[H:51]] _

input = 'CC1=C(CCC(O)=O)/C2=C/C3=N/C(=C\\C4=C(C)C(C=C)=C(N4)/C=C4\\N=C(\\C=C\\1/N\\2)C(C=C)=C4C)/C(C)=C3CCC(O)=O'
output = '[H:43]/[c:1]1/[c:9]2[c:5]([c:6]([c:10]([n:37]2[H:73])/[c:2]([c:15]/3\\[n:36][c:16](/[c:4]([c:12]\\4/[c:8]([c:7](/[c:1...4]([H:71])([H:72])[C:26](=[O:40])[O:42][H:76])/[H:44])[C:27]([H:53])([H:54])[H:55])[C:23](=[C:21]([H:47])[H:48])[H:51]'

    @using_openeye
    @pytest.mark.parametrize("input, output", get_smiles_lists(get_fn('drug_bank_stereo.smi'), get_fn('drug_bank_mapped_smi_oe.smi')))
    def test_drug_bank_oe(input, output):
        """
    
        Parameters
        ----------
        input
        output
    
        Returns
        -------
    
        """
        mol = oechem.OEMol()
        oechem.OEParseSmiles(mol, input)
>       assert cmiles.utils.mol_to_smiles(mol, mapped=True, isomeric=True, explicit_hydrogen=True) == output
E       AssertionError: assert '[H:43][c:1]1...[H:48])[H:51]' == '[H:43]/[c:1]...[H:48])[H:51]'
E         - [H:43]/[c:1]1/[c:9]2[c:5]([c:6]([c:10]([n:37]2[H:73])/[c:2]([c:15]/3\[n:36][c:16](/[c:4]([c:12]\4/[c:8]([c:7](/[c:11](/[n:38]4[H:74])[c:3](/[c:13]5[n:35]\[c:14]1\[C:18](=[C:17]5[C:24](=[C:22]([H:49])[H:50])[H:52])[C:29]([H:59])([H:60])[H:61])\[H:45])[C:28]([H:56])([H:57])[H:58])[C:31]([H:65])([H:66])[C:33]([H:69])([H:70])[C:25](=[O:39])[O:41][H:75])/[H:46])[C:20](=[C:19]3[C:30]([H:62])([H:63])[H:64])[C:32]([H:67])([H:68])[C:34]([H:71])([H:72])[C:26](=[O:40])[O:42][H:76])/[H:44])[C:27]([H:53])([H:54])[H:55])[C:23](=[C:21]([H:47])[H:48])[H:51]
E         ?       ^^^^^^^^           ...
E         
E         ...Full output truncated (3 lines hidden), use '-vv' to show

../test_cmiles.py:318: AssertionError
_ test_drug_bank_oe[CC1=C(CCC(O)=O)/C2=C/C3=N/C(=C\\C4=C(C)C(CCC(O)=O)=C(N4)/C=C4\\N=C(\\C=C\\1/N\\2)C(CCC(O)=O)=C4C)/C(CCC(O)=O)=C3C-[H:49]/[c:1]1/[c:9]2[c:5]([c:7]([c:11]([n:39]2[H:81])/[c:3]([c:16]/3\\[n:38][c:14](/[c:2]([c:10]\\4/[c:6]([c:8](/[c:12](/[n:40]4[H:82])[c:4](/[c:15]5[n:37]\\[c:13]1\\[C:19](=[C:17]5[C:27]([H:59])([H:60])[H:61])[C:31]([H:69])([H:70])[C:35]([H:77])([H:78])[C:23](=[O:43])[O:47][H:85])\\[H:52])[C:30]([H:67])([H:68])[C:34]([H:75])([H:76])[C:22](=[O:42])[O:46][H:84])[C:26]([H:56])([H:57])[H:58])/[H:50])[C:20](=[C:18]3[C:28]([H:62])([H:63])[H:64])[C:32]([H:71])([H:72])[C:36]([H:79])([H:80])[C:24](=[O:44])[O:48][H:86])/[H:51])[C:29]([H:65])([H:66])[C:33]([H:73])([H:74])[C:21](=[O:41])[O:45][H:83])[C:25]([H:53])([H:54])[H:55]] _

input = 'CC1=C(CCC(O)=O)/C2=C/C3=N/C(=C\\C4=C(C)C(CCC(O)=O)=C(N4)/C=C4\\N=C(\\C=C\\1/N\\2)C(CCC(O)=O)=C4C)/C(CCC(O)=O)=C3C'
output = '[H:49]/[c:1]1/[c:9]2[c:5]([c:7]([c:11]([n:39]2[H:81])/[c:3]([c:16]/3\\[n:38][c:14](/[c:2]([c:10]\\4/[c:6]([c:8](/[c:1...48][H:86])/[H:51])[C:29]([H:65])([H:66])[C:33]([H:73])([H:74])[C:21](=[O:41])[O:45][H:83])[C:25]([H:53])([H:54])[H:55]'

    @using_openeye
    @pytest.mark.parametrize("input, output", get_smiles_lists(get_fn('drug_bank_stereo.smi'), get_fn('drug_bank_mapped_smi_oe.smi')))
    def test_drug_bank_oe(input, output):
        """
    
        Parameters
        ----------
        input
        output
    
        Returns
        -------
    
        """
        mol = oechem.OEMol()
        oechem.OEParseSmiles(mol, input)
>       assert cmiles.utils.mol_to_smiles(mol, mapped=True, isomeric=True, explicit_hydrogen=True) == output
E       AssertionError: assert '[H:49][c:1]1...[H:54])[H:55]' == '[H:49]/[c:1]...[H:54])[H:55]'
E         - [H:49]/[c:1]1/[c:9]2[c:5]([c:7]([c:11]([n:39]2[H:81])/[c:3]([c:16]/3\[n:38][c:14](/[c:2]([c:10]\4/[c:6]([c:8](/[c:12](/[n:40]4[H:82])[c:4](/[c:15]5[n:37]\[c:13]1\[C:19](=[C:17]5[C:27]([H:59])([H:60])[H:61])[C:31]([H:69])([H:70])[C:35]([H:77])([H:78])[C:23](=[O:43])[O:47][H:85])\[H:52])[C:30]([H:67])([H:68])[C:34]([H:75])([H:76])[C:22](=[O:42])[O:46][H:84])[C:26]([H:56])([H:57])[H:58])/[H:50])[C:20](=[C:18]3[C:28]([H:62])([H:63])[H:64])[C:32]([H:71])([H:72])[C:36]([H:79])([H:80])[C:24](=[O:44])[O:48][H:86])/[H:51])[C:29]([H:65])([H:66])[C:33]([H:73])([H:74])[C:21](=[O:...
E         
E         ...Full output truncated (4 lines hidden), use '-vv' to show

../test_cmiles.py:318: AssertionError
_ test_drug_bank_oe[[Mg++].CCC1=C(C=O)C2=N\\C\\1=C/C1=C(C)C3=C([N-]1)\\C([C@@H](C(=O)OC)C3=O)=C1/N=C(/C=C3\\[N-]/C(=C\\2)C(C=C)=C3C)[C@@H](C)[C@@H]1CCC(=O)OC\\C=C(/C)CCC[C@H](C)CCC[C@H](C)CCCC(C)C-[H:67]/[c:1]/1[c:9]/2\\[c:5]([c:8](/[c:11](/[n-:56]2)[c:3](/[c:15]3[n:59]/[c:16]([c:6]/4\\[c:12]5[c:4]([c:7]([c:10]([n-:57]5)/[c:2]([c:14]/6\\[n:58][c:13]1[C:18](=[C:19]6[C:40]([H:108])([H:109])[C:34]([H:90])([H:91])[H:92])[C:22](=[O:61])[H:73])/[H:68])[C:30]([H:78])([H:79])[H:80])[C:17](=[O:60])[C@:27]4([H:75])[C:25](=[O:62])[O:64][C:39]([H:105])([H:106])[H:107])/[C@@:29]([C@:28]3([H:76])[C:33]([H:87])([H:88])[H:89])([H:77])[C:44]([H:116])([H:117])[C:43]([H:114])([H:115])[C:26](=[O:63])[O:65][C:41]([H:110])([H:111])/[C:23](=[C:24](\\[C:32]([H:84])([H:85])[H:86])/[C:42]([H:112])([H:113])[C:45]([H:118])([H:119])[C:48]([H:124])([H:125])[C@:54]([H:135])([C:37]([H:99])([H:100])[H:101])[C:51]([H:130])([H:131])[C:47]([H:122])([H:123])[C:52]([H:132])([H:133])[C@:55]([H:136])([C:38]([H:102])([H:103])[H:104])[C:50]([H:128])([H:129])[C:46]([H:120])([H:121])[C:49]([H:126])([H:127])[C:53]([H:134])([C:35]([H:93])([H:94])[H:95])[C:36]([H:96])([H:97])[H:98])/[H:74])\\[H:69])[C:31]([H:81])([H:82])[H:83])[C:21](=[C:20]([H:70])[H:71])[H:72].[Mg+2:66]] _

input = '[Mg++].CCC1=C(C=O)C2=N\\C\\1=C/C1=C(C)C3=C([N-]1)\\C([C@@H](C(=O)OC)C3=O)=C1/N=C(/C=C3\\[N-]/C(=C\\2)C(C=C)=C3C)[C@@H](C)[C@@H]1CCC(=O)OC\\C=C(/C)CCC[C@H](C)CCC[C@H](C)CCCC(C)C'
output = '[H:67]/[c:1]/1[c:9]/2\\[c:5]([c:8](/[c:11](/[n-:56]2)[c:3](/[c:15]3[n:59]/[c:16]([c:6]/4\\[c:12]5[c:4]([c:7]([c:10]([...:36]([H:96])([H:97])[H:98])/[H:74])\\[H:69])[C:31]([H:81])([H:82])[H:83])[C:21](=[C:20]([H:70])[H:71])[H:72].[Mg+2:66]'

    @using_openeye
    @pytest.mark.parametrize("input, output", get_smiles_lists(get_fn('drug_bank_stereo.smi'), get_fn('drug_bank_mapped_smi_oe.smi')))
    def test_drug_bank_oe(input, output):
        """
    
        Parameters
        ----------
        input
        output
    
        Returns
        -------
    
        """
        mol = oechem.OEMol()
        oechem.OEParseSmiles(mol, input)
>       assert cmiles.utils.mol_to_smiles(mol, mapped=True, isomeric=True, explicit_hydrogen=True) == output
E       AssertionError: assert '[H:67][c:1]1...72].[Mg+2:66]' == '[H:67]/[c:1]...72].[Mg+2:66]'
E         - [H:67]/[c:1]/1[c:9]/2\[c:5]([c:8](/[c:11](/[n-:56]2)[c:3](/[c:15]3[n:59]/[c:16]([c:6]/4\[c:12]5[c:4]([c:7]([c:10]([n-:57]5)/[c:2]([c:14]/6\[n:58][c:13]1[C:18](=[C:19]6[C:40]([H:108])([H:109])[C:34]([H:90])([H:91])[H:92])[C:22](=[O:61])[H:73])/[H:68])[C:30]([H:78])([H:79])[H:80])[C:17](=[O:60])[C@:27]4([H:75])[C:25](=[O:62])[O:64][C:39]([H:105])([H:106])[H:107])/[C@@:29]([C@:28]3([H:76])[C:33]([H:87])([H:88])[H:89])([H:77])[C:44]([H:116])([H:117])[C:43]([H:114])([H:115])[C:26](=[O:63])[O:65][C:41]([H:110])([H:111])/[C:23](=[C:24](\[C:32]([H:84])([H:85])[H:86])/[C:42]([...
E         
E         ...Full output truncated (4 lines hidden), use '-vv' to show

../test_cmiles.py:318: AssertionError
_ test_drug_bank_oe[[Cl-].[Cl-].[Sn+4].CCC1=C2[N-]C(\\C=C3/N=C(/C=C4\\[N-]\\C(=C/C5=N/C(=C\\2)/C(C)=C5CC)C(C)=C4CCC(O)=O)C(CCC(O)=O)=C3C)=C1C-[H:46]/[c:1]1/[c:9]2[c:5]([c:7]([c:11]([n-:35]2)/[c:3]([c:15]/3\\[n:38][c:14](/[c:2]([c:10]\\4/[c:6]([c:8](/[c:12](/[n-:36]4)[c:4](/[c:16]5[n:37]\\[c:13]1\\[C:17](=[C:20]5[C:32]([H:74])([H:75])[C:34]([H:78])([H:79])[C:22](=[O:40])[O:42][H:81])[C:25]([H:56])([H:57])[H:58])\\[H:49])[C:30]([H:70])([H:71])[C:33]([H:76])([H:77])[C:21](=[O:39])[O:41][H:80])[C:24]([H:53])([H:54])[H:55])/[H:47])[C:19](=[C:18]3[C:26]([H:59])([H:60])[H:61])[C:31]([H:72])([H:73])[C:28]([H:65])([H:66])[H:67])/[H:48])[C:29]([H:68])([H:69])[C:27]([H:62])([H:63])[H:64])[C:23]([H:50])([H:51])[H:52].[Cl-:43].[Cl-:44].[Sn+4:45]] _

input = '[Cl-].[Cl-].[Sn+4].CCC1=C2[N-]C(\\C=C3/N=C(/C=C4\\[N-]\\C(=C/C5=N/C(=C\\2)/C(C)=C5CC)C(C)=C4CCC(O)=O)C(CCC(O)=O)=C3C)=C1C'
output = '[H:46]/[c:1]1/[c:9]2[c:5]([c:7]([c:11]([n-:35]2)/[c:3]([c:15]/3\\[n:38][c:14](/[c:2]([c:10]\\4/[c:6]([c:8](/[c:12](/[...7])/[H:48])[C:29]([H:68])([H:69])[C:27]([H:62])([H:63])[H:64])[C:23]([H:50])([H:51])[H:52].[Cl-:43].[Cl-:44].[Sn+4:45]'

    @using_openeye
    @pytest.mark.parametrize("input, output", get_smiles_lists(get_fn('drug_bank_stereo.smi'), get_fn('drug_bank_mapped_smi_oe.smi')))
    def test_drug_bank_oe(input, output):
        """
    
        Parameters
        ----------
        input
        output
    
        Returns
        -------
    
        """
        mol = oechem.OEMol()
        oechem.OEParseSmiles(mol, input)
>       assert cmiles.utils.mol_to_smiles(mol, mapped=True, isomeric=True, explicit_hydrogen=True) == output
E       AssertionError: assert '[H:46][c:1]1...44].[Sn+4:45]' == '[H:46]/[c:1]...44].[Sn+4:45]'
E         - [H:46]/[c:1]1/[c:9]2[c:5]([c:7]([c:11]([n-:35]2)/[c:3]([c:15]/3\[n:38][c:14](/[c:2]([c:10]\4/[c:6]([c:8](/[c:12](/[n-:36]4)[c:4](/[c:16]5[n:37]\[c:13]1\[C:17](=[C:20]5[C:32]([H:74])([H:75])[C:34]([H:78])([H:79])[C:22](=[O:40])[O:42][H:81])[C:25]([H:56])([H:57])[H:58])\[H:49])[C:30]([H:70])([H:71])[C:33]([H:76])([H:77])[C:21](=[O:39])[O:41][H:80])[C:24]([H:53])([H:54])[H:55])/[H:47])[C:19](=[C:18]3[C:26]([H:59])([H:60])[H:61])[C:31]([H:72])([H:73])[C:28]([H:65])([H:66])[H:67])/[H:48])[C:29]([H:68])([H:69])[C:27]([H:62])([H:63])[H:64])[C:23]([H:50])([H:51])[H:52].[Cl-:4...
E         
E         ...Full output truncated (4 lines hidden), use '-vv' to show

../test_cmiles.py:318: AssertionError
_ test_drug_bank_oe[O.[Lu+3].CC([O-])=O.CC([O-])=O.[H]/C1=C2/N=C(/C(/[H])=C3\\[N-]/C(=C([H])\\C4=N\\C(=C(/[H])\\N=C5\\C=C(OCCOCCOCCOC)C(OCCOCCOCCOC)=C\\C\\5=N\\1)\\C(C)=C4CCCO)C(CC)=C3CC)C(CCCO)=C2C-[H:75]/[c:2]/1[c:10]/2\\[c:8]([c:7](/[c:9](/[n-:53]2)[c:1](/[c:15]3[n:56]/[c:17]([c:5](\\[n:54][c:11]/4\\[c:3]([c:13]([c:14]([c:4](\\[c:12]4[n:55]\\[c:6]([c:18]/5\\[n:57][c:16]1[C:20](=[C:22]5[C:26]([H:83])([H:84])[H:85])[C:36]([H:110])([H:111])[C:38]([H:114])([H:115])[C:40]([H:118])([H:119])[O:64][H:147])\\[H:79])[H:77])[O:66][C:42]([H:122])([H:123])[C:46]([H:130])([H:131])[O:70][C:50]([H:138])([H:139])[C:52]([H:142])([H:143])[O:72][C:48]([H:134])([H:135])[C:44]([H:126])([H:127])[O:68][C:32]([H:101])([H:102])[H:103])[O:65][C:41]([H:120])([H:121])[C:45]([H:128])([H:129])[O:69][C:49]([H:136])([H:137])[C:51]([H:140])([H:141])[O:71][C:47]([H:132])([H:133])[C:43]([H:124])([H:125])[O:67][C:31]([H:98])([H:99])[H:100])[H:76])/[H:78])/[C:21](=[C:19]3[C:35]([H:108])([H:109])[C:37]([H:112])([H:113])[C:39]([H:116])([H:117])[O:63][H:146])[C:25]([H:80])([H:81])[H:82])\\[H:74])[C:33]([H:104])([H:105])[C:29]([H:92])([H:93])[H:94])[C:34]([H:106])([H:107])[C:30]([H:95])([H:96])[H:97].[H:86][C:27]([H:87])([H:88])[C:23](=[O:60])[O-:58].[H:89][C:28]([H:90])([H:91])[C:24](=[O:61])[O-:59].[H:144][O:62][H:145].[Lu+3:73]] _

input = 'O.[Lu+3].CC([O-])=O.CC([O-])=O.[H]/C1=C2/N=C(/C(/[H])=C3\\[N-]/C(=C([H])\\C4=N\\C(=C(/[H])\\N=C5\\C=C(OCCOCCOCCOC)C(OCCOCCOCCOC)=C\\C\\5=N\\1)\\C(C)=C4CCCO)C(CC)=C3CC)C(CCCO)=C2C'
output = '[H:75]/[c:2]/1[c:10]/2\\[c:8]([c:7](/[c:9](/[n-:53]2)[c:1](/[c:15]3[n:56]/[c:17]([c:5](\\[n:54][c:11]/4\\[c:3]([c:13]...H:87])([H:88])[C:23](=[O:60])[O-:58].[H:89][C:28]([H:90])([H:91])[C:24](=[O:61])[O-:59].[H:144][O:62][H:145].[Lu+3:73]'

    @using_openeye
    @pytest.mark.parametrize("input, output", get_smiles_lists(get_fn('drug_bank_stereo.smi'), get_fn('drug_bank_mapped_smi_oe.smi')))
    def test_drug_bank_oe(input, output):
        """
    
        Parameters
        ----------
        input
        output
    
        Returns
        -------
    
        """
        mol = oechem.OEMol()
        oechem.OEParseSmiles(mol, input)
>       assert cmiles.utils.mol_to_smiles(mol, mapped=True, isomeric=True, explicit_hydrogen=True) == output
E       AssertionError: assert '[H:75][c:2]1...45].[Lu+3:73]' == '[H:75]/[c:2]...45].[Lu+3:73]'
E         - [H:75]/[c:2]/1[c:10]/2\[c:8]([c:7](/[c:9](/[n-:53]2)[c:1](/[c:15]3[n:56]/[c:17]([c:5](\[n:54][c:11]/4\[c:3]([c:13]([c:14]([c:4](\[c:12]4[n:55]\[c:6]([c:18]/5\[n:57][c:16]1[C:20](=[C:22]5[C:26]([H:83])([H:84])[H:85])[C:36]([H:110])([H:111])[C:38]([H:114])([H:115])[C:40]([H:118])([H:119])[O:64][H:147])\[H:79])[H:77])[O:66][C:42]([H:122])([H:123])[C:46]([H:130])([H:131])[O:70][C:50]([H:138])([H:139])[C:52]([H:142])([H:143])[O:72][C:48]([H:134])([H:135])[C:44]([H:126])([H:127])[O:68][C:32]([H:101])([H:102])[H:103])[O:65][C:41]([H:120])([H:121])[C:45]([H:128])([H:129])[O:6...
E         
E         ...Full output truncated (2 lines hidden), use '-vv' to show

../test_cmiles.py:318: AssertionError
_ test_drug_bank_oe[[Gd+3].CC([O-])=O.CC([O-])=O.CCC1=C(CC)/C2=C/C3=N/C(=C\\N=C4/C=C(OCCOCCOCCOC)C(OCCOCCOCCOC)=C/C/4=N\\C=C4/N=C(/C=C\\1\\[N-]\\2)C(CCCO)=C4C)/C(C)=C3CCCO-[H:73]/[c:1]1/[c:15]2[n:56]/[c:17]([c:5](\\[n:54][c:11]/3\\[c:12]([n:55]\\[c:6]([c:18]\\4/[n:57][c:16](/[c:2]([c:10]/5\\[n-:53]\\[c:9]1\\[c:7]([c:8]5[C:34]([C:30]([H:94])([H:95])[H:96])([H:105])[H:106])[C:33]([C:29]([H:91])([H:92])[H:93])([H:103])[H:104])/[H:74])[C:20](=[C:22]4[C:26]([H:82])([H:83])[H:84])[C:36]([C:38]([C:40]([O:63][H:144])([H:117])[H:118])([H:113])[H:114])([H:109])[H:110])\\[H:78])\\[c:4]([c:14]([c:13]([c:3]3[H:75])[O:64][C:41]([C:45]([O:68][C:49]([C:51]([O:70][C:47]([C:43]([O:66][C:31]([H:97])([H:98])[H:99])([H:123])[H:124])([H:131])[H:132])([H:139])[H:140])([H:135])[H:136])([H:127])[H:128])([H:119])[H:120])[O:65][C:42]([C:46]([O:69][C:50]([C:52]([O:71][C:48]([C:44]([O:67][C:32]([H:100])([H:101])[H:102])([H:125])[H:126])([H:133])[H:134])([H:141])[H:142])([H:137])[H:138])([H:129])[H:130])([H:121])[H:122])[H:76])/[H:77])/[C:21](=[C:19]2[C:35]([C:37]([C:39]([O:62][H:143])([H:115])[H:116])([H:111])[H:112])([H:107])[H:108])[C:25]([H:79])([H:80])[H:81].[H:85][C:27]([C:23](=[O:60])[O-:58])([H:86])[H:87].[H:88][C:28]([C:24](=[O:61])[O-:59])([H:89])[H:90].[Gd+3:72]] _

input = '[Gd+3].CC([O-])=O.CC([O-])=O.CCC1=C(CC)/C2=C/C3=N/C(=C\\N=C4/C=C(OCCOCCOCCOC)C(OCCOCCOCCOC)=C/C/4=N\\C=C4/N=C(/C=C\\1\\[N-]\\2)C(CCCO)=C4C)/C(C)=C3CCCO'
output = '[H:73]/[c:1]1/[c:15]2[n:56]/[c:17]([c:5](\\[n:54][c:11]/3\\[c:12]([n:55]\\[c:6]([c:18]\\4/[n:57][c:16](/[c:2]([c:10]/...[H:81].[H:85][C:27]([C:23](=[O:60])[O-:58])([H:86])[H:87].[H:88][C:28]([C:24](=[O:61])[O-:59])([H:89])[H:90].[Gd+3:72]'

    @using_openeye
    @pytest.mark.parametrize("input, output", get_smiles_lists(get_fn('drug_bank_stereo.smi'), get_fn('drug_bank_mapped_smi_oe.smi')))
    def test_drug_bank_oe(input, output):
        """
    
        Parameters
        ----------
        input
        output
    
        Returns
        -------
    
        """
        mol = oechem.OEMol()
        oechem.OEParseSmiles(mol, input)
>       assert cmiles.utils.mol_to_smiles(mol, mapped=True, isomeric=True, explicit_hydrogen=True) == output
E       AssertionError: assert '[H:73][c:1]1...90].[Gd+3:72]' == '[H:73]/[c:1]...90].[Gd+3:72]'
E         - [H:73]/[c:1]1/[c:15]2[n:56]/[c:17]([c:5](\[n:54][c:11]/3\[c:12]([n:55]\[c:6]([c:18]\4/[n:57][c:16](/[c:2]([c:10]/5\[n-:53]\[c:9]1\[c:7]([c:8]5[C:34]([C:30]([H:94])([H:95])[H:96])([H:105])[H:106])[C:33]([C:29]([H:91])([H:92])[H:93])([H:103])[H:104])/[H:74])[C:20](=[C:22]4[C:26]([H:82])([H:83])[H:84])[C:36]([C:38]([C:40]([O:63][H:144])([H:117])[H:118])([H:113])[H:114])([H:109])[H:110])\[H:78])\[c:4]([c:14]([c:13]([c:3]3[H:75])[O:64][C:41]([C:45]([O:68][C:49]([C:51]([O:70][C:47]([C:43]([O:66][C:31]([H:97])([H:98])[H:99])([H:123])[H:124])([H:131])[H:132])([H:139])[H:140])...
E         
E         ...Full output truncated (2 lines hidden), use '-vv' to show

../test_cmiles.py:318: AssertionError
----------------------------- Captured stderr call -----------------------------
Warning: Problem parsing SMILES:
Warning: Inconsistent cis/trans bond stereo.
Warning: [Gd+3].CC([O-])=O.CC([O-])=O.CCC1=C(CC)/C2=C/C3=N/C(=C\N=C4/C=C(OCCOCCOCCOC)C(OCCOCCOCCOC)=C/C/4=N\C=C4/N=C(/C=C\1\[N-]\2)C(CCCO)=C4C)/C(C)=C3CCCO
_ test_drug_bank_oe[CCC1=C(C)\\C2=C\\C3=C(C=C)C(C)=C(N3)\\C=C3/N=C([C@@H](CCC(O)=O)[C@@H]3C)/C(/CC(=O)N[C@@H](CC(O)=O)C(O)=O)=C3\\N\\C(=C/C1=N2)C(C)=C3C(O)=O-[H:53]/[c:1]1/[c:9]2[c:4]([c:6]([c:11]([n:41]2[H:87])/[c:3]([c:15]/3\\[n:40][c:16](/[c:8]([c:12]\\4/[c:5]([c:7](/[c:10](/[n:42]4[H:88])[c:2](/[c:14]5[n:39]\\[c:13]1\\[C:17](=[C:18]5[C:34]([H:78])([H:79])[C:32]([H:73])([H:74])[H:75])[C:30]([H:67])([H:68])[H:69])\\[H:54])[C:29]([H:64])([H:65])[H:66])[C:21](=[O:44])[O:49][H:90])/[C:33]([H:76])([H:77])[C:22](=[O:45])[N:43]([H:89])[C@:38]([H:86])([C:25](=[O:48])[O:52][H:93])[C:36]([H:82])([H:83])[C:24](=[O:47])[O:51][H:92])[C@@:27]([C@:26]3([H:59])[C:31]([H:70])([H:71])[H:72])([H:60])[C:37]([H:84])([H:85])[C:35]([H:80])([H:81])[C:23](=[O:46])[O:50][H:91])/[H:55])[C:28]([H:61])([H:62])[H:63])[C:20](=[C:19]([H:56])[H:57])[H:58]] _

input = 'CCC1=C(C)\\C2=C\\C3=C(C=C)C(C)=C(N3)\\C=C3/N=C([C@@H](CCC(O)=O)[C@@H]3C)/C(/CC(=O)N[C@@H](CC(O)=O)C(O)=O)=C3\\N\\C(=C/C1=N2)C(C)=C3C(O)=O'
output = '[H:53]/[c:1]1/[c:9]2[c:4]([c:6]([c:11]([n:41]2[H:87])/[c:3]([c:15]/3\\[n:40][c:16](/[c:8]([c:12]\\4/[c:5]([c:7](/[c:1...5]([H:80])([H:81])[C:23](=[O:46])[O:50][H:91])/[H:55])[C:28]([H:61])([H:62])[H:63])[C:20](=[C:19]([H:56])[H:57])[H:58]'

    @using_openeye
    @pytest.mark.parametrize("input, output", get_smiles_lists(get_fn('drug_bank_stereo.smi'), get_fn('drug_bank_mapped_smi_oe.smi')))
    def test_drug_bank_oe(input, output):
        """
    
        Parameters
        ----------
        input
        output
    
        Returns
        -------
    
        """
        mol = oechem.OEMol()
        oechem.OEParseSmiles(mol, input)
>       assert cmiles.utils.mol_to_smiles(mol, mapped=True, isomeric=True, explicit_hydrogen=True) == output
E       AssertionError: assert '[H:53][c:1]1...[H:57])[H:58]' == '[H:53]/[c:1]...[H:57])[H:58]'
E         - [H:53]/[c:1]1/[c:9]2[c:4]([c:6]([c:11]([n:41]2[H:87])/[c:3]([c:15]/3\[n:40][c:16](/[c:8]([c:12]\4/[c:5]([c:7](/[c:10](/[n:42]4[H:88])[c:2](/[c:14]5[n:39]\[c:13]1\[C:17](=[C:18]5[C:34]([H:78])([H:79])[C:32]([H:73])([H:74])[H:75])[C:30]([H:67])([H:68])[H:69])\[H:54])[C:29]([H:64])([H:65])[H:66])[C:21](=[O:44])[O:49][H:90])/[C:33]([H:76])([H:77])[C:22](=[O:45])[N:43]([H:89])[C@:38]([H:86])([C:25](=[O:48])[O:52][H:93])[C:36]([H:82])([H:83])[C:24](=[O:47])[O:51][H:92])[C@@:27]([C@:26]3([H:59])[C:31]([H:70])([H:71])[H:72])([H:60])[C:37]([H:84])([H:85])[C:35]([H:80])([H:81])...
E         
E         ...Full output truncated (4 lines hidden), use '-vv' to show

../test_cmiles.py:318: AssertionError
_ test_drug_bank_oe[N1C2=C3C=CC=CC3=C1\\N=C1/N=C(/N=C3\\N=C(NC4=N\\C(=N/2)C2=CC=CC=C42)C2=CC=CC=C32)C2=CC=CC=C12-[H:41][c:1]1[c:2]([c:10]([c:18]2[c:17]([c:9]1[H:49])[c:25]3/[n:33][c:27]/4\\[n:35][c:29](/[n:36][c:30]/5\\[n:38][c:32]([n:40]([c:31]-6[n:37]/[c:28]([n:34]\\[c:26]2[n:39]3[H:57])/[c:21]7[c:23]6[c:15]([c:7]([c:5]([c:13]7[H:53])[H:45])[H:47])[H:55])[H:58])-[c:24]8[c:22]5[c:14]([c:6]([c:8]([c:16]8[H:56])[H:48])[H:46])[H:54])-[c:20]9[c:19]4[c:11]([c:3]([c:4]([c:12]9[H:52])[H:44])[H:43])[H:51])[H:50])[H:42]] _

input = 'N1C2=C3C=CC=CC3=C1\\N=C1/N=C(/N=C3\\N=C(NC4=N\\C(=N/2)C2=CC=CC=C42)C2=CC=CC=C32)C2=CC=CC=C12'
output = '[H:41][c:1]1[c:2]([c:10]([c:18]2[c:17]([c:9]1[H:49])[c:25]3/[n:33][c:27]/4\\[n:35][c:29](/[n:36][c:30]/5\\[n:38][c:32...([c:16]8[H:56])[H:48])[H:46])[H:54])-[c:20]9[c:19]4[c:11]([c:3]([c:4]([c:12]9[H:52])[H:44])[H:43])[H:51])[H:50])[H:42]'

    @using_openeye
    @pytest.mark.parametrize("input, output", get_smiles_lists(get_fn('drug_bank_stereo.smi'), get_fn('drug_bank_mapped_smi_oe.smi')))
    def test_drug_bank_oe(input, output):
        """
    
        Parameters
        ----------
        input
        output
    
        Returns
        -------
    
        """
        mol = oechem.OEMol()
        oechem.OEParseSmiles(mol, input)
>       assert cmiles.utils.mol_to_smiles(mol, mapped=True, isomeric=True, explicit_hydrogen=True) == output
E       AssertionError: assert '[H:41][c:1]1...[H:50])[H:42]' == '[H:41][c:1]1...[H:50])[H:42]'
E         - [H:41][c:1]1[c:2]([c:10]([c:18]2[c:17]([c:9]1[H:49])[c:25]3/[n:33][c:27]/4\[n:35][c:29](/[n:36][c:30]/5\[n:38][c:32]([n:40]([c:31]-6[n:37]/[c:28]([n:34]\[c:26]2[n:39]3[H:57])/[c:21]7[c:23]6[c:15]([c:7]([c:5]([c:13]7[H:53])[H:45])[H:47])[H:55])[H:58])-[c:24]8[c:22]5[c:14]([c:6]([c:8]([c:16]8[H:56])[H:48])[H:46])[H:54])-[c:20]9[c:19]4[c:11]([c:3]([c:4]([c:12]9[H:52])[H:44])[H:43])[H:51])[H:50])[H:42]
E         + [H:41][c:1]1[c:2]([c:10]([c:18]2[c:17]([c:9]1[H:49])[c:25]3[n:33][c:27]-4[n:35][c:29]([n:36][c:30]-5[n:38][c:32]([n:40]([c:31]-6[n:37][c:28]([n:34][c:26]2[n:39]3[H:57])-[c...
E         
E         ...Full output truncated (1 line hidden), use '-vv' to show

../test_cmiles.py:318: AssertionError
=========================== short test summary info ============================
FAILED ../test_cmiles.py::test_drug_bank_oe[COC(=O)CCC1=C2NC(\\C=C3/N=C(/C=C4\\N\\C(=C/C5=N/C(=C\\2)/C(CCC(O)=O)=C5C)C(C=C)=C4C)C2=CC=C([C@@H](C(=O)OC)[C@@]32C)C(=O)OC)=C1C-[H:54]/[c:1]/1[c:9]/2\\[c:5]([c:6](/[c:10](/[n:44]2[H:93])[c:2](/[c:13]3[n:43]/[c:16]([c:4](\\[c:12]4[c:7]([c:8]([c:11]([n:45]4[H:94])/[c:3]([c:15]/5\\[n:42][c:14]1[C:20](=[C:21]5[C:39]([H:87])([H:88])[C:40]([H:89])([H:90])[C:27](=[O:48])[O:50][H:95])[C:33]([H:70])([H:71])[H:72])/[H:56])[C:38]([H:85])([H:86])[C:41]([H:91])([H:92])[C:28](=[O:49])[O:53][C:37]([H:82])([H:83])[H:84])[C:32]([H:67])([H:68])[H:69])/[H:57])/[C@:30]6([C:19]3=[C:17]([C:18](=[C:22]([C@@:29]6([H:63])[C:26](=[O:47])[O:52][C:36]([H:79])([H:80])[H:81])[C:25](=[O:46])[O:51][C:35]([H:76])([H:77])[H:78])[H:59])[H:58])[C:34]([H:73])([H:74])[H:75])\\[H:55])[C:31]([H:64])([H:65])[H:66])[C:24](=[C:23]([H:60])[H:61])[H:62]]
FAILED ../test_cmiles.py::test_drug_bank_oe[[H][C@]1(CCC(=O)OC\\C=C(/C)CCC[C@H](C)CCC[C@H](C)CCCC(C)C)[C@H](C)\\C2=C\\C3=C(C)C(C(C)=O)=C4\\C=C5/N=C(/C=C6\\N([Mg]N34)C3=C([C@@H](C(=O)OC)C(=O)C3=C6C)C1=N2)[C@H](CC)[C@H]5C-[H:67]/[c:1]1/[c:9]2[c:5]([c:8]([c:11]/3[n:58]2[Mg:66][n:59]4/[c:10]([c:2](\\[c:14]5[n:56]\\[c:13]1\\[C@:24]([C@@:26]5([H:74])[C:43]([H:118])([H:119])[C:34]([H:94])([H:95])[H:96])([H:72])[C:32]([H:88])([H:89])[H:90])/[H:68])/[c:7]([c:4]6[c:12]4[c:6]([c:16]7[n:57]/[c:15]([c:3]3/[H:69])/[C@@:25]([C@:27]7([H:75])[C:44]([H:120])([H:121])[C:42]([H:116])([H:117])[C:22](=[O:63])[O:65][C:40]([H:112])([H:113])/[C:18](=[C:20](\\[C:31]([H:85])([H:86])[H:87])/[C:41]([H:114])([H:115])[C:45]([H:122])([H:123])[C:48]([H:128])([H:129])[C@:54]([H:139])([C:37]([H:103])([H:104])[H:105])[C:51]([H:134])([H:135])[C:47]([H:126])([H:127])[C:52]([H:136])([H:137])[C@:55]([H:140])([C:38]([H:106])([H:107])[H:108])[C:50]([H:132])([H:133])[C:46]([H:124])([H:125])[C:49]([H:130])([H:131])[C:53]([H:138])([C:35]([H:97])([H:98])[H:99])[C:36]([H:100])([H:101])[H:102])/[H:70])([H:73])[C:33]([H:91])([H:92])[H:93])[C@@:23]([C:17]6=[O:60])([H:71])[C:21](=[O:62])[O:64][C:39]([H:109])([H:110])[H:111])[C:28]([H:76])([H:77])[H:78])[C:29]([H:79])([H:80])[H:81])[C:19](=[O:61])[C:30]([H:82])([H:83])[H:84]]
FAILED ../test_cmiles.py::test_drug_bank_oe[CCC1=C(C)\\C2=C\\C3=C(C=C)C(C)=C4\\C=C5/N=C([C@@H](CCC(=O)OC\\C=C(/C)CCC[C@H](C)CCC[C@H](C)CCCC(C)C)[C@@H]5C)C5=C6N([Mg]N34)\\C(=C/C1=N2)C(C)=C6C(=O)[C@@H]5C(=O)OC-[H:66]/[c:1]1/[c:9]2[c:5]([c:8]([c:11]/3[n:58]2[Mg:65][n:59]4/[c:10]([c:2](\\[c:14]5[n:56]\\[c:13]1\\[C:18](=[C:19]5[C:40]([H:109])([H:110])[C:34]([H:91])([H:92])[H:93])[C:31]([H:82])([H:83])[H:84])/[H:67])/[c:7]([c:4]6[c:12]4[c:6]([c:16]7[n:57]/[c:15]([c:3]3/[H:68])/[C@@:27]([C@:28]7([H:75])[C:44]([H:117])([H:118])[C:43]([H:115])([H:116])[C:25](=[O:62])[O:64][C:41]([H:111])([H:112])/[C:22](=[C:23](\\[C:32]([H:85])([H:86])[H:87])/[C:42]([H:113])([H:114])[C:45]([H:119])([H:120])[C:48]([H:125])([H:126])[C@:54]([H:136])([C:37]([H:100])([H:101])[H:102])[C:51]([H:131])([H:132])[C:47]([H:123])([H:124])[C:52]([H:133])([H:134])[C@:55]([H:137])([C:38]([H:103])([H:104])[H:105])[C:50]([H:129])([H:130])[C:46]([H:121])([H:122])[C:49]([H:127])([H:128])[C:53]([H:135])([C:35]([H:94])([H:95])[H:96])[C:36]([H:97])([H:98])[H:99])/[H:72])([H:74])[C:33]([H:88])([H:89])[H:90])[C@@:26]([C:17]6=[O:60])([H:73])[C:24](=[O:61])[O:63][C:39]([H:106])([H:107])[H:108])[C:29]([H:76])([H:77])[H:78])[C:30]([H:79])([H:80])[H:81])[C:21](=[C:20]([H:69])[H:70])[H:71]]
FAILED ../test_cmiles.py::test_drug_bank_oe[[Co+7].[H]\\C-1=C2\\[N-]\\C(=C([H])/C3=N/C(=C([H])\\C4=C(CCC([O-])=O)C(C)=C(N4)\\C([H])=C4\\C=C(C)C-1=N4)/C(CCC(O)=O)=C3C)C(C)=C2-[H:40][c:1]\\1[c:6](/[c:10]/2[c:3](/[c:14]3[n:33]/[c:16]([c:5](\\[c:12]4[c:8]([c:7]([c:11]([n:34]4[H:66])/[c:4]([c:15]/5\\[n:32][c:13](/[c:2]([c:9]1\\[n-:31]2)/[H:41])[C:18](=[C:17]5[H:45])[C:25]([H:52])([H:53])[H:54])/[H:43])[C:24]([H:49])([H:50])[H:51])[C:27]([H:58])([H:59])[C:29]([H:62])([H:63])[C:21](=[O:36])[O-:35])/[H:44])/[C:20](=[C:19]3[C:26]([H:55])([H:56])[H:57])[C:28]([H:60])([H:61])[C:30]([H:64])([H:65])[C:22](=[O:37])[O:38][H:67])\\[H:42])[C:23]([H:46])([H:47])[H:48].[Co+7:39]]
FAILED ../test_cmiles.py::test_drug_bank_oe[CC1=C(CCC(O)=O)/C2=C/C3=N/C(=C\\C4=C(C)C(C=C)=C(N4)/C=C4\\N=C(\\C=C\\1/N\\2)C(C=C)=C4C)/C(C)=C3CCC(O)=O-[H:43]/[c:1]1/[c:9]2[c:5]([c:6]([c:10]([n:37]2[H:73])/[c:2]([c:15]/3\\[n:36][c:16](/[c:4]([c:12]\\4/[c:8]([c:7](/[c:11](/[n:38]4[H:74])[c:3](/[c:13]5[n:35]\\[c:14]1\\[C:18](=[C:17]5[C:24](=[C:22]([H:49])[H:50])[H:52])[C:29]([H:59])([H:60])[H:61])\\[H:45])[C:28]([H:56])([H:57])[H:58])[C:31]([H:65])([H:66])[C:33]([H:69])([H:70])[C:25](=[O:39])[O:41][H:75])/[H:46])[C:20](=[C:19]3[C:30]([H:62])([H:63])[H:64])[C:32]([H:67])([H:68])[C:34]([H:71])([H:72])[C:26](=[O:40])[O:42][H:76])/[H:44])[C:27]([H:53])([H:54])[H:55])[C:23](=[C:21]([H:47])[H:48])[H:51]]
FAILED ../test_cmiles.py::test_drug_bank_oe[CC1=C(CCC(O)=O)/C2=C/C3=N/C(=C\\C4=C(C)C(CCC(O)=O)=C(N4)/C=C4\\N=C(\\C=C\\1/N\\2)C(CCC(O)=O)=C4C)/C(CCC(O)=O)=C3C-[H:49]/[c:1]1/[c:9]2[c:5]([c:7]([c:11]([n:39]2[H:81])/[c:3]([c:16]/3\\[n:38][c:14](/[c:2]([c:10]\\4/[c:6]([c:8](/[c:12](/[n:40]4[H:82])[c:4](/[c:15]5[n:37]\\[c:13]1\\[C:19](=[C:17]5[C:27]([H:59])([H:60])[H:61])[C:31]([H:69])([H:70])[C:35]([H:77])([H:78])[C:23](=[O:43])[O:47][H:85])\\[H:52])[C:30]([H:67])([H:68])[C:34]([H:75])([H:76])[C:22](=[O:42])[O:46][H:84])[C:26]([H:56])([H:57])[H:58])/[H:50])[C:20](=[C:18]3[C:28]([H:62])([H:63])[H:64])[C:32]([H:71])([H:72])[C:36]([H:79])([H:80])[C:24](=[O:44])[O:48][H:86])/[H:51])[C:29]([H:65])([H:66])[C:33]([H:73])([H:74])[C:21](=[O:41])[O:45][H:83])[C:25]([H:53])([H:54])[H:55]]
FAILED ../test_cmiles.py::test_drug_bank_oe[[Mg++].CCC1=C(C=O)C2=N\\C\\1=C/C1=C(C)C3=C([N-]1)\\C([C@@H](C(=O)OC)C3=O)=C1/N=C(/C=C3\\[N-]/C(=C\\2)C(C=C)=C3C)[C@@H](C)[C@@H]1CCC(=O)OC\\C=C(/C)CCC[C@H](C)CCC[C@H](C)CCCC(C)C-[H:67]/[c:1]/1[c:9]/2\\[c:5]([c:8](/[c:11](/[n-:56]2)[c:3](/[c:15]3[n:59]/[c:16]([c:6]/4\\[c:12]5[c:4]([c:7]([c:10]([n-:57]5)/[c:2]([c:14]/6\\[n:58][c:13]1[C:18](=[C:19]6[C:40]([H:108])([H:109])[C:34]([H:90])([H:91])[H:92])[C:22](=[O:61])[H:73])/[H:68])[C:30]([H:78])([H:79])[H:80])[C:17](=[O:60])[C@:27]4([H:75])[C:25](=[O:62])[O:64][C:39]([H:105])([H:106])[H:107])/[C@@:29]([C@:28]3([H:76])[C:33]([H:87])([H:88])[H:89])([H:77])[C:44]([H:116])([H:117])[C:43]([H:114])([H:115])[C:26](=[O:63])[O:65][C:41]([H:110])([H:111])/[C:23](=[C:24](\\[C:32]([H:84])([H:85])[H:86])/[C:42]([H:112])([H:113])[C:45]([H:118])([H:119])[C:48]([H:124])([H:125])[C@:54]([H:135])([C:37]([H:99])([H:100])[H:101])[C:51]([H:130])([H:131])[C:47]([H:122])([H:123])[C:52]([H:132])([H:133])[C@:55]([H:136])([C:38]([H:102])([H:103])[H:104])[C:50]([H:128])([H:129])[C:46]([H:120])([H:121])[C:49]([H:126])([H:127])[C:53]([H:134])([C:35]([H:93])([H:94])[H:95])[C:36]([H:96])([H:97])[H:98])/[H:74])\\[H:69])[C:31]([H:81])([H:82])[H:83])[C:21](=[C:20]([H:70])[H:71])[H:72].[Mg+2:66]]
FAILED ../test_cmiles.py::test_drug_bank_oe[[Cl-].[Cl-].[Sn+4].CCC1=C2[N-]C(\\C=C3/N=C(/C=C4\\[N-]\\C(=C/C5=N/C(=C\\2)/C(C)=C5CC)C(C)=C4CCC(O)=O)C(CCC(O)=O)=C3C)=C1C-[H:46]/[c:1]1/[c:9]2[c:5]([c:7]([c:11]([n-:35]2)/[c:3]([c:15]/3\\[n:38][c:14](/[c:2]([c:10]\\4/[c:6]([c:8](/[c:12](/[n-:36]4)[c:4](/[c:16]5[n:37]\\[c:13]1\\[C:17](=[C:20]5[C:32]([H:74])([H:75])[C:34]([H:78])([H:79])[C:22](=[O:40])[O:42][H:81])[C:25]([H:56])([H:57])[H:58])\\[H:49])[C:30]([H:70])([H:71])[C:33]([H:76])([H:77])[C:21](=[O:39])[O:41][H:80])[C:24]([H:53])([H:54])[H:55])/[H:47])[C:19](=[C:18]3[C:26]([H:59])([H:60])[H:61])[C:31]([H:72])([H:73])[C:28]([H:65])([H:66])[H:67])/[H:48])[C:29]([H:68])([H:69])[C:27]([H:62])([H:63])[H:64])[C:23]([H:50])([H:51])[H:52].[Cl-:43].[Cl-:44].[Sn+4:45]]
FAILED ../test_cmiles.py::test_drug_bank_oe[O.[Lu+3].CC([O-])=O.CC([O-])=O.[H]/C1=C2/N=C(/C(/[H])=C3\\[N-]/C(=C([H])\\C4=N\\C(=C(/[H])\\N=C5\\C=C(OCCOCCOCCOC)C(OCCOCCOCCOC)=C\\C\\5=N\\1)\\C(C)=C4CCCO)C(CC)=C3CC)C(CCCO)=C2C-[H:75]/[c:2]/1[c:10]/2\\[c:8]([c:7](/[c:9](/[n-:53]2)[c:1](/[c:15]3[n:56]/[c:17]([c:5](\\[n:54][c:11]/4\\[c:3]([c:13]([c:14]([c:4](\\[c:12]4[n:55]\\[c:6]([c:18]/5\\[n:57][c:16]1[C:20](=[C:22]5[C:26]([H:83])([H:84])[H:85])[C:36]([H:110])([H:111])[C:38]([H:114])([H:115])[C:40]([H:118])([H:119])[O:64][H:147])\\[H:79])[H:77])[O:66][C:42]([H:122])([H:123])[C:46]([H:130])([H:131])[O:70][C:50]([H:138])([H:139])[C:52]([H:142])([H:143])[O:72][C:48]([H:134])([H:135])[C:44]([H:126])([H:127])[O:68][C:32]([H:101])([H:102])[H:103])[O:65][C:41]([H:120])([H:121])[C:45]([H:128])([H:129])[O:69][C:49]([H:136])([H:137])[C:51]([H:140])([H:141])[O:71][C:47]([H:132])([H:133])[C:43]([H:124])([H:125])[O:67][C:31]([H:98])([H:99])[H:100])[H:76])/[H:78])/[C:21](=[C:19]3[C:35]([H:108])([H:109])[C:37]([H:112])([H:113])[C:39]([H:116])([H:117])[O:63][H:146])[C:25]([H:80])([H:81])[H:82])\\[H:74])[C:33]([H:104])([H:105])[C:29]([H:92])([H:93])[H:94])[C:34]([H:106])([H:107])[C:30]([H:95])([H:96])[H:97].[H:86][C:27]([H:87])([H:88])[C:23](=[O:60])[O-:58].[H:89][C:28]([H:90])([H:91])[C:24](=[O:61])[O-:59].[H:144][O:62][H:145].[Lu+3:73]]
FAILED ../test_cmiles.py::test_drug_bank_oe[[Gd+3].CC([O-])=O.CC([O-])=O.CCC1=C(CC)/C2=C/C3=N/C(=C\\N=C4/C=C(OCCOCCOCCOC)C(OCCOCCOCCOC)=C/C/4=N\\C=C4/N=C(/C=C\\1\\[N-]\\2)C(CCCO)=C4C)/C(C)=C3CCCO-[H:73]/[c:1]1/[c:15]2[n:56]/[c:17]([c:5](\\[n:54][c:11]/3\\[c:12]([n:55]\\[c:6]([c:18]\\4/[n:57][c:16](/[c:2]([c:10]/5\\[n-:53]\\[c:9]1\\[c:7]([c:8]5[C:34]([C:30]([H:94])([H:95])[H:96])([H:105])[H:106])[C:33]([C:29]([H:91])([H:92])[H:93])([H:103])[H:104])/[H:74])[C:20](=[C:22]4[C:26]([H:82])([H:83])[H:84])[C:36]([C:38]([C:40]([O:63][H:144])([H:117])[H:118])([H:113])[H:114])([H:109])[H:110])\\[H:78])\\[c:4]([c:14]([c:13]([c:3]3[H:75])[O:64][C:41]([C:45]([O:68][C:49]([C:51]([O:70][C:47]([C:43]([O:66][C:31]([H:97])([H:98])[H:99])([H:123])[H:124])([H:131])[H:132])([H:139])[H:140])([H:135])[H:136])([H:127])[H:128])([H:119])[H:120])[O:65][C:42]([C:46]([O:69][C:50]([C:52]([O:71][C:48]([C:44]([O:67][C:32]([H:100])([H:101])[H:102])([H:125])[H:126])([H:133])[H:134])([H:141])[H:142])([H:137])[H:138])([H:129])[H:130])([H:121])[H:122])[H:76])/[H:77])/[C:21](=[C:19]2[C:35]([C:37]([C:39]([O:62][H:143])([H:115])[H:116])([H:111])[H:112])([H:107])[H:108])[C:25]([H:79])([H:80])[H:81].[H:85][C:27]([C:23](=[O:60])[O-:58])([H:86])[H:87].[H:88][C:28]([C:24](=[O:61])[O-:59])([H:89])[H:90].[Gd+3:72]]
FAILED ../test_cmiles.py::test_drug_bank_oe[CCC1=C(C)\\C2=C\\C3=C(C=C)C(C)=C(N3)\\C=C3/N=C([C@@H](CCC(O)=O)[C@@H]3C)/C(/CC(=O)N[C@@H](CC(O)=O)C(O)=O)=C3\\N\\C(=C/C1=N2)C(C)=C3C(O)=O-[H:53]/[c:1]1/[c:9]2[c:4]([c:6]([c:11]([n:41]2[H:87])/[c:3]([c:15]/3\\[n:40][c:16](/[c:8]([c:12]\\4/[c:5]([c:7](/[c:10](/[n:42]4[H:88])[c:2](/[c:14]5[n:39]\\[c:13]1\\[C:17](=[C:18]5[C:34]([H:78])([H:79])[C:32]([H:73])([H:74])[H:75])[C:30]([H:67])([H:68])[H:69])\\[H:54])[C:29]([H:64])([H:65])[H:66])[C:21](=[O:44])[O:49][H:90])/[C:33]([H:76])([H:77])[C:22](=[O:45])[N:43]([H:89])[C@:38]([H:86])([C:25](=[O:48])[O:52][H:93])[C:36]([H:82])([H:83])[C:24](=[O:47])[O:51][H:92])[C@@:27]([C@:26]3([H:59])[C:31]([H:70])([H:71])[H:72])([H:60])[C:37]([H:84])([H:85])[C:35]([H:80])([H:81])[C:23](=[O:46])[O:50][H:91])/[H:55])[C:28]([H:61])([H:62])[H:63])[C:20](=[C:19]([H:56])[H:57])[H:58]]
FAILED ../test_cmiles.py::test_drug_bank_oe[N1C2=C3C=CC=CC3=C1\\N=C1/N=C(/N=C3\\N=C(NC4=N\\C(=N/2)C2=CC=CC=C42)C2=CC=CC=C32)C2=CC=CC=C12-[H:41][c:1]1[c:2]([c:10]([c:18]2[c:17]([c:9]1[H:49])[c:25]3/[n:33][c:27]/4\\[n:35][c:29](/[n:36][c:30]/5\\[n:38][c:32]([n:40]([c:31]-6[n:37]/[c:28]([n:34]\\[c:26]2[n:39]3[H:57])/[c:21]7[c:23]6[c:15]([c:7]([c:5]([c:13]7[H:53])[H:45])[H:47])[H:55])[H:58])-[c:24]8[c:22]5[c:14]([c:6]([c:8]([c:16]8[H:56])[H:48])[H:46])[H:54])-[c:20]9[c:19]4[c:11]([c:3]([c:4]([c:12]9[H:52])[H:44])[H:43])[H:51])[H:50])[H:42]]
============================== 12 failed in 4.37s ==============================

Connectivity table

Should cmiles also add the connectivity table as another identifier? The indices will be based on the map indices but 0 indexed rather than 1 indexed. Currently fragmenter generates a connectivity table for the molecule.
pinging @dgasmith, @jchodera

WARNING: Proton(s) added/removed

When calling

cmiles_ids = cmiles.get_molecule_ids(smiles)

I noticed lots of warnings like

[21:36:18] WARNING: Proton(s) added/removed

Since any addition of protons would cause the mapped atoms to get all screwed up, isn't this a bad thing? Should we throw an exception in these cases?

How to update reference files for new versions of RDKit

A stripped-down version of what I did in #44:

  1. Update the toolkit: conda update rdkit -c conda-forge
  2. Run this script to re-generate the reference files cd cmiles/tests/reference/ ; python generate_reference.py
  3. Also update the generated files in test_cmiles.py (search in file for something like _rd_2020)
  4. Run tests (which should pass for small toolkit changes) pytest -r fE /path/to/cmiles/
  5. Make sure the conda env file referenced in CI (.github/workflows/CI.yml) matches the installed, updated version
  6. Add files git add cmiles/tests/reference/*2020* cmiles/tests/test_cmiles.py
  7. Commit git commit -m "Update test files for RDKit x.y.z"
  8. Open the PR

This may work the same for OpenEye changes, but I have not encountered them yet.

IUPAC name and chemical formula

Add IUPAC names and chemical formula. The chemical formula should follow the same standardization as the QCArchive project.

@dgasmith, can you let me know how you generate the chemical formula?

Better parsing of molecule inputs

Arguably trivial but it would be nice to handle the wrong input separately from checking that toolkit(s) are installed. Here I accidentally pass in an OpenFF Molecule and confused myself since I knew I had the toolkits installed

In [1]: import cmiles

In [2]: from openforcefield.topology.molecule import Molecule
Warning: Unable to load toolkit 'AmberTools'.
_ColormakerRegistry()

In [3]: cmiles.utils.mol_to_smiles(Molecule.from_smiles('C'))
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-3-f0a9fb86fb26> in <module>
----> 1 cmiles.utils.mol_to_smiles(Molecule.from_smiles('C'))

~/software/cmiles/cmiles/utils.py in mol_to_smiles(molecule, **kwargs)
    165     """
    166     molecule = copy.deepcopy(molecule)
--> 167     toolkit = _set_toolkit(molecule)
    168     if has_atom_map(molecule):
    169         remove_atom_map(molecule)

~/software/cmiles/cmiles/utils.py in _set_toolkit(molecule)
    556         import cmiles._cmiles_rd as toolkit
    557     else:
--> 558         raise RuntimeError("Must have openeye or rdkit installed")
    559     return toolkit
    560

RuntimeError: Must have openeye or rdkit installed

In [4]: cmiles.utils.mol_to_smiles(Molecule.from_smiles('C').to_openeye())
Out[4]: '[H:2][C:1]([H:3])([H:4])[H:5]'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.