Exemplo n.º 1
0
def filterReactions(reactants, products, reactionList):
    """
    Remove any reactions from the given `reactionList` whose reactants do
    not involve all the given `reactants` or whose products do not involve
    all the given `products`. This method checks both forward and reverse
    directions, and only filters out reactions that don't match either.
    """

    # Convert from molecules to species and generate resonance isomers.
    reactant_species = []
    for mol in reactants:
        s = RMGSpecies(molecule=mol)
        s.generateResonanceIsomers()
        reactant_species.append(s)
    reactants = reactant_species
    product_species = []
    for mol in products:
        s = RMGSpecies(molecule=mol)
        s.generateResonanceIsomers()
        product_species.append(s)
    products = product_species

    reactions = reactionList[:]

    for reaction in reactionList:
        # Forward direction
        reactants0 = [r for r in reaction.reactants]
        for reactant in reactants:
            for reactant0 in reactants0:
                if reactant.isIsomorphic(reactant0):
                    reactants0.remove(reactant0)
                    break
        products0 = [p for p in reaction.products]
        for product in products:
            for product0 in products0:
                if product.isIsomorphic(product0):
                    products0.remove(product0)
                    break
        forward = not (len(reactants0) != 0 or len(products0) != 0)
        # Reverse direction
        reactants0 = [r for r in reaction.products]
        for reactant in reactants:
            for reactant0 in reactants0:
                if reactant.isIsomorphic(reactant0):
                    reactants0.remove(reactant0)
                    break
        products0 = [p for p in reaction.reactants]
        for product in products:
            for product0 in products0:
                if product.isIsomorphic(product0):
                    products0.remove(product0)
                    break
        reverse = not (len(reactants0) != 0 or len(products0) != 0)
        if not forward and not reverse:
            reactions.remove(reaction)
    return reactions
Exemplo n.º 2
0
    def calculate_symmetry_number(self):

        numbers = self.ase_molecule.numbers
        positions = self.ase_molecule.positions

        mol = RMGMolecule()
        mol.from_xyz(numbers, positions)
        try:
            species = RMGSpecies(molecule=[mol])
            self._symmetry_number = species.get_symmetry_number()
        except ValueError:
            self._symmetry_number = mol.get_symmetry_number()

        return self._symmetry_number
Exemplo n.º 3
0
    def __init__(self, smiles=[], rmg_species=None):
        """
        A class that holds information for Species object
        """

        assert isinstance(smiles, list)

        self._conformers = None

        if ((len(smiles) != 0) and rmg_species):
            # Provide both a list of smiles and an rmg_species
            assert isinstance(
                rmg_species,
                (rmgpy.molecule.Molecule,
                 rmgpy.species.Species))

            if isinstance(rmg_species, rmgpy.molecule.Molecule):
                rmg_species = RMGSpecies(molecule=[rmg_species])
                try:
                    rmg_species.generate_resonance_structures()
                except:
                    logging.info(
                        "Could not generate resonance structures for this species... Using molecule provided")

            else:
                try:
                    rmg_species.generate_resonance_structures()
                except:
                    logging.info(
                        "Could not generate resonance structures for this species... Using molecule provided")

            smiles_list = []
            for rmg_mol in rmg_species.molecule:
                smiles_list.append(rmg_mol.toSMILES())

            for s in smiles_list:
                if s in smiles:
                    continue
                if not(s in smiles):
                    smiles.append(s)

            assert len(smiles) == len(
                smiles_list), "The list of smiles presented does not match the possible species provided"

            self.smiles = smiles
            self.rmg_species = rmg_species

        elif (rmg_species and (len(smiles) == 0)):
            # RMG species provided, but not smiles

            assert isinstance(
                rmg_species,
                (rmgpy.molecule.Molecule,
                 rmgpy.species.Species))

            if isinstance(rmg_species, rmgpy.molecule.Molecule):
                rmg_species = RMGSpecies(molecule=[rmg_species])
                try:
                    rmg_species.generate_resonance_structures()
                except:
                    logging.info(
                        "Could not generate resonance structures for this species... Using molecule provided")

            else:
                try:
                    rmg_species.generate_resonance_structures()
                except:
                    logging.info(
                        "Could not generate resonance structures for this species... Using molecule provided")

            smiles = []
            for rmg_mol in rmg_species.molecule:
                smiles.append(rmg_mol.toSMILES())

            self.smiles = smiles
            self.rmg_species = rmg_species

        elif ((not rmg_species) and (len(smiles) != 0)):
            # smiles provided but not species

            species_list = []
            for smile in smiles:
                molecule = RMGMolecule(SMILES=smile)
                species_list.append(molecule.generate_resonance_structures())

            if len(smiles) != 1:
                got_one = False
                for s1 in species_list:
                    for s2 in species_list:
                        for m1 in s1:
                            for m2 in s2:
                                if m1.isIsomorphic(m2):
                                    got_one = True
                assert got_one, "SMILESs provided describe different species"

            smiles_list = []
            for mol in species_list[0]:
                smiles_list.append(mol.toSMILES())

            self.smiles = smiles_list
            self.rmg_species = species_list[0]

        else:
            self.smiles = []
            self.rmg_species = rmg_species
Exemplo n.º 4
0
    def __init__(self, smiles=[], rmg_species=None):

        assert isinstance(smiles, list)

        self._conformers = None

        if ((len(smiles) != 0) and rmg_species):
            # Provide both a list of smiles and an rmg_species
            assert isinstance(rmg_species,
                              (rmgpy.molecule.Molecule, rmgpy.species.Species))

            if isinstance(rmg_species, rmgpy.molecule.Molecule):
                rmg_species = RMGSpecies(molecule=[rmg_species])
                rmg_species.generate_resonance_structures()

            else:
                rmg_species.generate_resonance_structures()

            smiles_list = []
            for rmg_mol in rmg_species.molecule:
                smiles_list.append(rmg_mol.toSMILES())

            for s in smiles_list:
                if s in smiles:
                    continue
                if not (s in smiles):
                    smiles.append(s)

            assert len(smiles) == len(
                smiles_list
            ), "The list of smiles presented does not match the possible species provided"

            self.smiles = smiles
            self.rmg_species = rmg_species

        elif (rmg_species and (len(smiles) == 0)):
            # RMG species provided, but not smiles

            assert isinstance(rmg_species,
                              (rmgpy.molecule.Molecule, rmgpy.species.Species))

            if isinstance(rmg_species, rmgpy.molecule.Molecule):
                rmg_species = RMGSpecies(molecule=[rmg_species])
                rmg_species.generate_resonance_structures()

            else:
                rmg_species.generate_resonance_structures()

            smiles = []
            for rmg_mol in rmg_species.molecule:
                smiles.append(rmg_mol.toSMILES())

            self.smiles = smiles
            self.rmg_species = rmg_species

        elif ((not rmg_species) and (len(smiles) != 0)):
            # smiles provided but not species

            species_list = []
            for smile in smiles:
                molecule = RMGMolecule(SMILES=smile)
                s = RMGSpecies(molecule=[molecule])
                s.generate_resonance_structures()
                species_list.append(s)

            for s1 in species_list:
                for s2 in species_list:
                    assert s1.isIsomorphic(
                        s2), "SMILESs provided describe different species"

            self.smiles = smiles
            self.rmg_species = species_list[0]

        else:
            self.smiles = []
            self.rmg_species = rmg_species
Exemplo n.º 5
0
    def getForwardReactionForFamilyEntry(self, entry, family, groups,
                                         rxnFamily):
        """
        For a given `entry` for a reaction of the given reaction `family` (the
        string label of the family), return the reaction with transition state
        distances for the "forward" direction as defined by the reaction
        family. For families that are their own reverse, the direction the
        kinetics is given in will be preserved. If the entry contains
        functional groups for the reactants, assume that it is given in the
        forward direction and do nothing. Returns the reaction in the direction
        consistent with the reaction family template, and the matching template.
        """
        def matchSpeciesToMolecules(species, molecules):
            if len(species) == len(molecules) == 1:
                return species[0].isIsomorphic(molecules[0])
            elif len(species) == len(molecules) == 2:
                if species[0].isIsomorphic(
                        molecules[0]) and species[1].isIsomorphic(
                            molecules[1]):
                    return True
                elif species[0].isIsomorphic(
                        molecules[1]) and species[1].isIsomorphic(
                            molecules[0]):
                    return True
            return False

        reaction = None
        template = None

        # Get the indicated reaction family
        if groups is None:
            raise ValueError(
                'Invalid value "{0}" for family parameter.'.format(family))

        if all([(isinstance(reactant, Group)
                 or isinstance(reactant, LogicNode))
                for reactant in entry.item.reactants]):
            # The entry is a rate rule, containing functional groups only
            # By convention, these are always given in the forward direction and
            # have kinetics defined on a per-site basis
            reaction = Reaction(
                reactants=entry.item.reactants[:],
                products=[],
                kinetics=entry.data,
                degeneracy=1,
            )
            template = [
                groups.entries[label] for label in entry.label.split(';')
            ]

        elif (all([
                isinstance(reactant, (RMGMolecule, RMGSpecies))
                for reactant in entry.item.reactants
        ]) and all([
                isinstance(product, (RMGMolecule, RMGSpecies))
                for product in entry.item.products
        ])):
            # The entry is a real reaction, containing molecules
            # These could be defined for either the forward or reverse direction
            # and could have a reaction-path degeneracy

            reaction = Reaction(reactants=[], products=[])
            for molecule in entry.item.reactants:
                if isinstance(molecule, RMGMolecule):
                    reactant = RMGSpecies(molecule=[molecule])
                else:
                    reactant = molecule
                reactant.generateResonanceIsomers()
                reaction.reactants.append(reactant)
            for molecule in entry.item.products:
                if isinstance(molecule, RMGMolecule):
                    product = RMGSpecies(molecule=[molecule])
                else:
                    product = molecule
                product.generateResonanceIsomers()
                reaction.products.append(product)

            # Generate all possible reactions involving the reactant species
            generatedReactions = self.generateReactionsFromFamilies(
                [reactant.molecule[0] for reactant in reaction.reactants], [],
                only_families=[family],
                families=rxnFamily)

            # Remove from that set any reactions that don't produce the desired
            # reactants and products
            forward = []
            reverse = []
            for rxn in generatedReactions:
                if matchSpeciesToMolecules(
                        reaction.reactants,
                        rxn.reactants) and matchSpeciesToMolecules(
                            reaction.products, rxn.products):
                    forward.append(rxn)
                if matchSpeciesToMolecules(
                        reaction.reactants,
                        rxn.products) and matchSpeciesToMolecules(
                            reaction.products, rxn.reactants):
                    reverse.append(rxn)

            # We should now know whether the reaction is given in the forward or
            # reverse direction
            if len(forward) == 1 and len(reverse) == 0:
                # The reaction is in the forward direction, so use as-is
                reaction = forward[0]
                template = reaction.template
                # Don't forget to overwrite the estimated distances from the
                # database with the distances for this entry
                reaction.distances = entry.data
            elif len(reverse) == 1 and len(forward) == 0:
                # The reaction is in the reverse direction
                # The reaction is in the forward direction, so use as-is
                reaction = forward[0]
                template = reaction.template
                # The distances to the H atom are reversed
                reaction.distances = entry.data
                reaction.distances['d12'] = entry.data['d23']
                reaction.distances['d23'] = entry.data['d12']
            elif len(reverse) > 0 and len(forward) > 0:
                print('FAIL: Multiple reactions found for {0!r}.'.format(
                    entry.label))
            elif len(reverse) == 0 and len(forward) == 0:
                print('FAIL: No reactions found for "%s".' % (entry.label))
            else:
                print('FAIL: Unable to estimate distances for {0!r}.'.format(
                    entry.label))

        assert reaction is not None
        assert template is not None
        return reaction, template