def toInChI(mol, backend='rdkit-first', aug_level=0): """ Convert a molecular structure to an InChI string. For aug_level=0, generates the canonical InChI. For aug_level=1, appends the molecule multiplicity. For aug_level=2, appends positions of unpaired and paired electrons. Uses RDKit or OpenBabel for conversion. Args: backend choice of backend, 'try-all', 'rdkit', or 'openbabel' aug_level level of augmentation, 0, 1, or 2 """ cython.declare(inchi=str, ulayer=str, player=str, mlayer=str) if aug_level == 0: return _write(mol, 'inchi', backend) elif aug_level == 1: inchi = toInChI(mol, backend=backend) mlayer = '/mult{0}'.format(mol.multiplicity) if mol.multiplicity != 0 else '' return inchi + mlayer elif aug_level == 2: inchi = toInChI(mol, backend=backend) ulayer, player = inchiutil.create_augmented_layers(mol) return inchiutil.compose_aug_inchi(inchi, ulayer, player) else: raise ValueError("Implemented values for aug_level are 0, 1, or 2.")
def compare(self, inchi, u_indices=None, p_indices=None): u_layer = U_LAYER_PREFIX + U_LAYER_SEPARATOR.join(map( str, u_indices)) if u_indices else None p_layer = P_LAYER_PREFIX + P_LAYER_SEPARATOR.join(map( str, p_indices)) if p_indices else None aug_inchi = compose_aug_inchi(inchi, u_layer, p_layer) mol = from_augmented_inchi(Molecule(), aug_inchi) ConsistencyChecker.check_multiplicity(mol.get_radical_count(), mol.multiplicity) for at in mol.atoms: ConsistencyChecker.check_partial_charge(at) spc = Species(molecule=[mol]) spc.generate_resonance_structures() ignore_prefix = r"(InChI=1+)(S*)/" aug_inchi_expected = re.split(ignore_prefix, aug_inchi)[-1] aug_inchi_computed = re.split(ignore_prefix, spc.get_augmented_inchi())[-1] self.assertEquals(aug_inchi_expected, aug_inchi_computed) return mol
def test_compose_aug_inchi(self): inchi = 'C2H5/c1-2/h1H2,2H3' mult = 2 aug_inchi = compose_aug_inchi(inchi, U_LAYER_PREFIX + str(mult)) self.assertTrue( aug_inchi == INCHI_PREFIX + '/' + inchi + U_LAYER_PREFIX + str(mult), aug_inchi)
def toAugmentedInChI(mol): """ Adds an extra layer to the InChI denoting the multiplicity of the molecule. Separate layer with a forward slash character. """ inchi = toInChI(mol) mult = createMultiplicityLayer(mol.multiplicity) ulayer = createULayer(mol) return compose_aug_inchi(inchi, mult, ulayer)
def compare(self, inchi, u_indices=None, p_indices=None): u_layer = U_LAYER_PREFIX + U_LAYER_SEPARATOR.join(map(str, u_indices)) if u_indices else None p_layer = P_LAYER_PREFIX + P_LAYER_SEPARATOR.join(map(str, p_indices)) if p_indices else None aug_inchi = compose_aug_inchi(inchi, u_layer, p_layer) mol = fromAugmentedInChI(Molecule(), aug_inchi) ConsistencyChecker.check_multiplicity(mol.getRadicalCount(), mol.multiplicity) for at in mol.atoms: ConsistencyChecker.check_partial_charge(at) spc = Species(molecule=[mol]) spc.generate_resonance_structures() ignore_prefix = r"(InChI=1+)(S*)/" aug_inchi_expected = re.split(ignore_prefix, aug_inchi)[-1] aug_inchi_computed = re.split(ignore_prefix, spc.getAugmentedInChI())[-1] self.assertEquals(aug_inchi_expected, aug_inchi_computed) return mol
def toAugmentedInChI(mol): """ This function generates the augmented InChI canonical identifier, and that allows for the differentiation between structures with spin states and multiple unpaired electrons. Two additional layers are added to the InChI: - unpaired electrons layer: the position of the unpaired electrons in the molecule """ cython.declare( inchi=str, ulayer=str, aug_inchi=str, ) inchi = toInChI(mol) ulayer, player = create_augmented_layers(mol) aug_inchi = inchiutil.compose_aug_inchi(inchi, ulayer, player) return aug_inchi