def generateRules(family, database):
    """
    For a given reaction `family` label, generate additional rate rules from
    the corresponding depository training set. This function does automatically
    what users used to do by hand to construct a rate rule from reaction
    kinetics found in the literature, i.e. determine the groups involved,
    adjust to a per-site basis, etc.
    """

    # Load rules and determine starting index
    rules = family.rules
    index = max([entry.index for entry in rules.entries.values()] or [0]) + 1

    # Load training entries
    for depository in family.depositories:
        if 'training' in depository.name:
            entries = sorted(depository.entries.values(),
                             key=lambda entry: (entry.index, entry.label))
            break

    # Generate a rate rule for each training entry
    for entry in entries:

        # Load entry's reaction, template, and kinetics
        reaction, template = database.kinetics.getForwardReactionForFamilyEntry(entry=entry,
                                                                                family=family.name,
                                                                                thermoDatabase=database.thermo)
        kinetics = reaction.kinetics

        # Convert KineticsData to Arrhenius
        if isinstance(kinetics, KineticsData):
            kinetics = Arrhenius().fitToData(Tdata=kinetics.Tdata.values,
                                             kdata=kinetics.kdata.values,
                                             kunits=kinetics.kdata.units,
                                             T0=1)

        # Ignore other kinetics types
        if not isinstance(kinetics, Arrhenius):
            continue

        # Change reference temperature to 1 K if necessary
        if kinetics.T0.value != 1:
            kinetics = kinetics.changeT0(1)

        # Convert kinetics to a per-site basis
        kinetics.A.value /= reaction.degeneracy

        # Convert to ArrheniusEP
        kinetics = ArrheniusEP(A=kinetics.A,
                               n=kinetics.n,
                               alpha=0,
                               E0=kinetics.Ea,
                               Tmin=kinetics.Tmin,
                               Tmax=kinetics.Tmax)

        # Add new rate rule
        rules.entries[index] = Entry(index=index,
                                     label=';'.join([group.label for group in template]),
                                     item=Reaction(reactants=template[:],
                                                   products=None),
                                     data=kinetics,
                                     reference=entry.reference,
                                     rank=entry.rank,
                                     shortDesc=entry.shortDesc,
                                     longDesc=entry.longDesc,
                                     history=entry.history)
        index += 1
def generateAdditionalRateRules(family, database):
    """
    For a given reaction `family` label, generate additional rate rules from
    the corresponding depository training set. This function does automatically
    what users used to do by hand to construct a rate rule from reaction
    kinetics found in the literature, i.e. determine the groups involved,
    adjust to a per-site basis, etc.
    """
    
    # Find the database components we will need
    rules = database.kinetics.depository['{0}/rules'.format(family)]
    groups = database.kinetics.groups[family]
    
    index = max([entry.index for entry in rules.entries.values()]) + 1
    
    for depositoryLabel in ['training']:
        depository = database.kinetics.depository['{0}/{1}'.format(family, depositoryLabel)]
        
        entries = depository.entries.values()
        entries.sort(key=lambda x: (x.index, x.label))
        
        for entry0 in entries:
            
            reaction, template = database.kinetics.getForwardReactionForFamilyEntry(entry=entry0, family=family, thermoDatabase=database.thermo)
            
            # We must convert the kinetics to ArrheniusEP to finish our rate rule
            kinetics = reaction.kinetics
            # If kinetics are KineticsData, then first convert to Arrhenius
            if isinstance(kinetics, KineticsData):
                kinetics = Arrhenius().fitToData(
                    Tdata=kinetics.Tdata.values,
                    kdata=kinetics.kdata.values,
                    kunits=kinetics.kdata.units,
                    T0=1,
                )
            
            # Now convert from Arrhenius to ArrheniusEP
            # If not Arrhenius (or KineticsData), then skip this entry
            if isinstance(kinetics, Arrhenius):
                if kinetics.T0.value != 1:
                    kinetics.changeT0(1)
                kinetics = ArrheniusEP(
                    A = kinetics.A,
                    n = kinetics.n,
                    alpha = 0,
                    E0 = kinetics.Ea,
                    Tmin = kinetics.Tmin,
                    Tmax = kinetics.Tmax,
                )
            else:
                break
            
            # Put the kinetics on a per-site basis
            kinetics.A.value /= reaction.degeneracy
                
            # Construct a new entry for the new rate rule
            label = ';'.join([group.label for group in template])
            item = Reaction(
                reactants = template[:],
                products = None,
            )
            entry = Entry(
                index = index,
                label = label,
                item = item,
                data = kinetics,
                reference = entry0.reference,
                rank = entry0.rank,
                shortDesc = entry0.shortDesc,
                longDesc = entry0.longDesc,
                history = entry0.history,
            )

            # Add the new rate rule to the depository of rate rules
            rules.entries[entry.index] = entry
            
            index += 1
def generateRules(family, database):
    """
    For a given reaction `family` label, generate additional rate rules from
    the corresponding depository training set. This function does automatically
    what users used to do by hand to construct a rate rule from reaction
    kinetics found in the literature, i.e. determine the groups involved,
    adjust to a per-site basis, etc.
    """

    # Load rules and determine starting index
    rules = family.rules
    index = max([entry.index for entry in rules.entries.values()] or [0]) + 1

    # Load training entries
    for depository in family.depositories:
        if 'training' in depository.name:
            entries = sorted(depository.entries.values(),
                             key=lambda entry: (entry.index, entry.label))
            break

    # Generate a rate rule for each training entry
    for entry in entries:

        # Load entry's reaction, template, and kinetics
        reaction, template = database.kinetics.getForwardReactionForFamilyEntry(
            entry=entry, family=family.name, thermoDatabase=database.thermo)
        kinetics = reaction.kinetics

        # Convert KineticsData to Arrhenius
        if isinstance(kinetics, KineticsData):
            kinetics = Arrhenius().fitToData(Tdata=kinetics.Tdata.values,
                                             kdata=kinetics.kdata.values,
                                             kunits=kinetics.kdata.units,
                                             T0=1)

        # Ignore other kinetics types
        if not isinstance(kinetics, Arrhenius):
            continue

        # Change reference temperature to 1 K if necessary
        if kinetics.T0.value != 1:
            kinetics = kinetics.changeT0(1)

        # Convert kinetics to a per-site basis
        kinetics.A.value /= reaction.degeneracy

        # Convert to ArrheniusEP
        kinetics = ArrheniusEP(A=kinetics.A,
                               n=kinetics.n,
                               alpha=0,
                               E0=kinetics.Ea,
                               Tmin=kinetics.Tmin,
                               Tmax=kinetics.Tmax)

        # Add new rate rule
        rules.entries[index] = Entry(index=index,
                                     label=';'.join(
                                         [group.label for group in template]),
                                     item=Reaction(reactants=template[:],
                                                   products=None),
                                     data=kinetics,
                                     reference=entry.reference,
                                     rank=entry.rank,
                                     shortDesc=entry.shortDesc,
                                     longDesc=entry.longDesc,
                                     history=entry.history)
        index += 1