def testIDReprBond(self):
     rxn = BO4
     # noinspection PyTypeChecker
     event1 = Event(rxn, [1, 2], DEF_RXN_RATES[rxn][(G, S)][MON_OLI], (4, 8))
     good_str = "Forming bo4 bond between indices [1, 2] (adjacency_matrix update (4, 8))"
     self.assertTrue(str(event1) == good_str)
     self.assertTrue(repr(event1) == good_str)
    def testB1BondGenMol(self):
        ini_mono_type_list = [S, S, S, G, S]
        sg_ratio = 1.0
        max_monos = 12
        random_num = 55
        initial_monomers = [
            Monomer(mono_type, i)
            for i, mono_type in enumerate(ini_mono_type_list)
        ]
        initial_events = create_initial_events(initial_monomers, DEF_RXN_RATES)
        initial_events.append(Event(GROW, [], rate=1e4))
        initial_state = create_initial_state(initial_events, initial_monomers)
        result = run_kmc(DEF_RXN_RATES,
                         initial_state,
                         initial_events,
                         n_max=max_monos,
                         t_max=2,
                         random_seed=random_num,
                         sg_ratio=sg_ratio)
        nodes = result[MONO_LIST]
        adj = result[ADJ_MATRIX]
        # generate_mol(adj, nodes)
        with capture_stderr(generate_mol, adj, nodes) as output:
            self.assertFalse(output)

        mol = MolFromMolBlock(generate_mol(adj, nodes))
        mols = GetMolFrags(mol)

        analysis = analyze_adj_matrix(adj)
        frag_sizes = analysis[CHAIN_LEN]

        # Make sure there are the same number of separate fragments calculated by RDKIT
        # as we get from just separating the alternate B1
        self.assertEqual(np.sum(list(frag_sizes.values())), len(mols))
예제 #3
0
def create_initial_events(initial_monomers, rxn_rates):
    """
    # Create event_dict that will oxidize every monomer
    :param initial_monomers: a list of Monomer objects
    :param rxn_rates: dict of dict of dicts of reaction rates in 1/s
    :return: a list of oxidation Event objects to initialize the state by allowing oxidation of every monomer
    """
    return [Event(OX, [mon.identity], rxn_rates[OX][mon.type][MONOMER]) for mon in initial_monomers]
def create_sample_kmc_result_c_lignin(num_monos=2, max_monos=12, seed=10):
    initial_monomers = [Monomer(C, i) for i in range(num_monos)]
    # noinspection PyTypeChecker
    initial_events = create_initial_events(initial_monomers, DEF_RXN_RATES)
    initial_state = create_initial_state(initial_events, initial_monomers)
    initial_events.append(Event(GROW, [], rate=1e4))
    result = run_kmc(DEF_RXN_RATES, initial_state, sorted(initial_events), n_max=max_monos, t_max=2, random_seed=seed)
    return result
 def testMissingRequiredSGRatio(self):
     # set up variable to allow running run_kmc without specifying sg_ratio
     initial_sg_ratio = 0.75
     num_initial_monos = 3
     monomer_draw = np.around(np.random.rand(num_initial_monos), MAX_NUM_DECIMAL)
     # these are tested separately
     initial_monomers = create_initial_monomers(initial_sg_ratio, monomer_draw)
     initial_events = create_initial_events(initial_monomers, DEF_RXN_RATES)
     initial_state = create_initial_state(initial_events, initial_monomers)
     events = {initial_events[i] for i in range(num_initial_monos)}
     events.add(Event(GROW, [], rate=1e4))
     try:
         run_kmc(DEF_RXN_RATES, initial_state, sorted(events), n_max=20, t_max=1, random_seed=10)
         self.assertFalse("Should not arrive here; An error should have be raised")
     except InvalidDataError as e:
         self.assertTrue("A numeric sg_ratio" in e.args[0])
def generate_lignin(num_monomers: int = 1) -> Chem.Mol:
    """Generates lignin molecule.

        parameters
        ----------
        num_monomers : int
                Number of monomers in lignin molecule.
        """
    # Set the percentage of S
    sg_ratio = 0
    pct_s = sg_ratio / (1 + sg_ratio)

    # Set the initial and maximum number of monomers to be modeled.
    ini_num_monos = 1
    max_num_monos = num_monomers

    # Maximum time to simulate, in seconds
    t_max = 1  # seconds
    mono_add_rate = 1e4  # monomers/second

    # Use a random number and the given sg_ratio to determine the monolignol types to be initially modeled
    monomer_draw = np.random.rand(ini_num_monos)
    initial_monomers = create_initial_monomers(pct_s, monomer_draw)

    # Initially allow only oxidation events. After they are used to determine the initial state, add
    #     GROW to the events, which allows additional monomers to be added to the reaction at the
    #     specified rate and with the specified ratio
    initial_events = create_initial_events(initial_monomers, rxn_rates)
    initial_state = create_initial_state(initial_events, initial_monomers)
    initial_events.append(Event(GROW, [], rate=mono_add_rate))

    # simulate lignin creation
    result = run_kmc(rxn_rates,
                     initial_state,
                     initial_events,
                     n_max=max_num_monos,
                     t_max=t_max,
                     sg_ratio=sg_ratio)
    # using RDKit
    nodes = result[MONO_LIST]
    adj = result[ADJ_MATRIX]
    block = generate_mol(adj, nodes)
    mol = MolFromMolBlock(block)
    mol = Chem.AddHs(mol)

    return mol
    def testIniRates(self):
        # Note: this test did not increase coverage. Added to help debug notebook.
        # run_multi = False
        # if run_multi:
        #     fun = par.delayed(run_kmc)
        #     num_jobs = num_repeats
        # else:
        num_repeats = 4

        # fun = None
        # num_jobs = None

        sg_ratio = 1.1

        # minimize random calls
        monomer_type_list = [S, G]
        initial_monomers = [Monomer(mono_type, i) for i, mono_type in enumerate(monomer_type_list)]
        max_monos = 12
        initial_events = create_initial_events(initial_monomers, DEF_RXN_RATES)
        # FYI: np.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, axis=0)[source]
        num_rates = 3
        add_rates = np.logspace(4, 12, num_rates)
        add_rates_result_list = []

        # will add to random seed in the iterations to insure using a different seed for each repeat
        random_seed = 2

        for add_rate in add_rates:
            initial_state = create_initial_state(initial_events, initial_monomers)
            initial_events.append(Event(GROW, [], rate=add_rate))
            # if run_multi:
            #     results = par.Parallel(n_jobs=num_jobs)([fun(DEF_RXN_RATES, initial_state, initial_events,
            #                                                  n_max=max_monos, t_max=1, sg_ratio=sg_ratio,
            #                                                  random_seed=(random_seed + i))
            #                                              for i in range(num_repeats)])
            # else:
            results = [run_kmc(DEF_RXN_RATES, initial_state, initial_events, n_max=max_monos, t_max=1,
                               sg_ratio=sg_ratio, random_seed=(random_seed + i)) for i in range(num_repeats)]
            add_rates_result_list.append(results)

        av_bo4_bonds, std_bo4_bonds = get_avg_num_bonds(BO4, num_rates, add_rates_result_list, num_repeats)

        good_av_bo4 = [0.3680555555555555, 0.2863636363636364, 0.03125]
        good_std_bo4 = [0.08187379251771941, 0.013636363636363641, 0.05412658773652741]
        self.assertTrue(np.allclose(av_bo4_bonds, good_av_bo4))
        self.assertTrue(np.allclose(std_bo4_bonds, good_std_bo4))
예제 #8
0
def initiate_state(add_rate, cfg, rep, sg_ratio):
    pct_s = sg_ratio / (1 + sg_ratio)
    ini_num_monos = cfg[INI_MONOS]
    if cfg[RANDOM_SEED]:
        # we don't want the same random seed for every iteration
        np.random.seed(cfg[RANDOM_SEED] + int(add_rate / 100 + sg_ratio * 10) + rep)
        monomer_draw = np.around(np.random.rand(ini_num_monos), MAX_NUM_DECIMAL)
    else:
        monomer_draw = np.random.rand(ini_num_monos)
    initial_monomers = create_initial_monomers(pct_s, monomer_draw)
    # initial event must be oxidation to create reactive species; all monomers may be oxidized
    initial_events = create_initial_events(initial_monomers, cfg[RXN_RATES])
    # initial_monomers and initial_events are grouped into the initial state
    initial_state = create_initial_state(initial_events, initial_monomers)
    if cfg[MAX_MONOS] > cfg[INI_MONOS]:
        initial_events.append(Event(GROW, [], rate=add_rate))
    elif cfg[MAX_MONOS] < cfg[INI_MONOS]:
        warning(f"The specified maximum number of monomers ({cfg[MAX_MONOS]}) is less than the "
                f"specified initial number of monomers ({cfg[INI_MONOS]}). \n The program will "
                f"proceed with the with the initial number of monomers with no addition of monomers.")
    return initial_events, initial_state
def create_sample_kmc_result(max_time=1., num_initial_monos=3, max_monos=10, sg_ratio=0.75, seed=10):
    # The set lists are to minimize randomness in testing (adding while debugging source of randomness in some tests;
    #     leaving because it doesn't hurt a thing; also leaving option to make a monomer_draw of arbitrary length
    #     using a seed, but rounding those numbers because the machine precision differences in floats was the bug
    np.random.seed(seed)
    if num_initial_monos == 3:
        monomer_draw = MONO_DRAW_3
    elif num_initial_monos == 20:
        monomer_draw = [0.77132064, 0.02075195, 0.63364823, 0.74880388, 0.49850701, 0.22479665, 0.19806286,
                        0.76053071, 0.16911084, 0.08833981, 0.68535982, 0.95339335, 0.00394827, 0.51219226,
                        0.81262096, 0.61252607, 0.72175532, 0.29187607, 0.91777412, 0.71457578]
    else:
        monomer_draw = np.around(np.random.rand(num_initial_monos), MAX_NUM_DECIMAL)

    # these are tested separately elsewhere
    initial_monomers = create_initial_monomers(sg_ratio, monomer_draw)
    initial_events = create_initial_events(initial_monomers, DEF_RXN_RATES)
    initial_state = OrderedDict(create_initial_state(initial_events, initial_monomers))
    initial_events.append(Event(GROW, [], rate=1e4))
    result = run_kmc(DEF_RXN_RATES, initial_state, initial_events, n_max=max_monos, t_max=max_time,
                     random_seed=10, sg_ratio=sg_ratio)
    return result
예제 #10
0
max_num_monos = 10

# Maximum time to simulate, in seconds
t_max = 1  # seconds
mono_add_rate = 1e4  # monomers/second

# Use a random number and the given sg_ratio to determine the monolignol types to be initially modeled
monomer_draw = np.random.rand(ini_num_monos)
initial_monomers = create_initial_monomers(pct_s, monomer_draw)

# Initially allow only oxidation events. After they are used to determine the initial state, add
#     GROW to the events, which allows additional monomers to be added to the reaction at the
#     specified rate and with the specified ratio
initial_events = create_initial_events(initial_monomers, rxn_rates)
initial_state = create_initial_state(initial_events, initial_monomers)
initial_events.append(Event(GROW, [], rate=mono_add_rate))

result = run_kmc(rxn_rates,
                 initial_state,
                 initial_events,
                 n_max=max_num_monos,
                 t_max=t_max,
                 sg_ratio=sg_ratio)

# Convert the sparse matrix to a full array before printing
print("The adjacency matrix for the simulated lignin is:")
print(result[ADJ_MATRIX].toarray())

# From the list of monomers and the adjacency matrix, we can use LigninKMC to write out a tcl script for psfgen to
# turn into a .psf file.
# fname and sgnames are things that we'd want to change; file name always the same as the segname
 def testIDRepr(self):
     rxn = OX
     # noinspection PyTypeChecker
     event1 = Event(rxn, [2], DEF_RXN_RATES[rxn][G][MONOMER])
     self.assertTrue(str(event1) == "Performing oxidation on index 2")