From 90e4ec06528b73db3eec46c94fcceb61dce7f4be Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Tue, 10 Dec 2024 15:59:33 -0700 Subject: [PATCH 01/32] Add forced swap mode --- ensemble_md/replica_exchange_EE.py | 122 +++++++++++++++++++++++------ 1 file changed, 98 insertions(+), 24 deletions(-) diff --git a/ensemble_md/replica_exchange_EE.py b/ensemble_md/replica_exchange_EE.py index 4500a4a..843dd14 100644 --- a/ensemble_md/replica_exchange_EE.py +++ b/ensemble_md/replica_exchange_EE.py @@ -196,7 +196,7 @@ def set_params(self, analysis): self.warnings.append(f'Warning: Parameter "{i}" specified in the input YAML file is not recognizable.') # Step 4: Check if the parameters in the YAML file are well-defined - if self.proposal not in [None, 'single', 'neighboring', 'exhaustive']: # deprecated option: multiple + if self.proposal not in [None, 'single', 'neighboring', 'exhaustive', 'forced_swap']: # deprecated option: multiple # noqa: E501 raise ParameterError("The specified proposal scheme is not available. Available options include 'single', 'neighboring', and 'exhaustive'.") # noqa: E501 if self.df_method not in [None, 'TI', 'BAR', 'MBAR']: @@ -791,7 +791,7 @@ def extract_final_log_info(self, log_files): return wl_delta, weights, counts @staticmethod - def identify_swappable_pairs(states, state_ranges, neighbor_exchange, add_swappables=None): + def identify_swappable_pairs(self, states, state_ranges, neighbor_exchange, add_swappables=None, iteration=None): """ Identifies swappable pairs. By definition, a pair of simulation is considered swappable only if their last sampled states are in the alchemical ranges of both simulations. This is required @@ -815,6 +815,9 @@ def identify_swappable_pairs(states, state_ranges, neighbor_exchange, add_swappa For example, :code:`add_swappables=[[4, 5], [14, 15]]` means that if a replica samples state 4, it can be swapped with another replica that samples state 5 and vice versa. The same logic applies to states 14 and 15. This parameter is only relevant to MT-REXEE simulations. + iteration : int + The iteration number will determine which direction the swaps will be performed. This option is + only necessary when using the "forced_swap" proposal scheme. Returns ------- @@ -838,26 +841,36 @@ def identify_swappable_pairs(states, state_ranges, neighbor_exchange, add_swappa """ n_sim = len(states) sim_idx = list(range(n_sim)) - all_pairs = list(combinations(sim_idx, 2)) + if self.proposal == 'forced_swap': + if iteration % 2 == 0: # Swap up for self.n_sim - 1 swaps + swappables = [] + for n in np.arange(0, self.n_sim-2, 2): + swappables.append([n, n+1]) + else: # and then swap down for self.n_sim - 1 swaps and repeat + swappables = [] + for n in np.arange(1, self.n_sim-2, 2): + swappables.append([n, n+1]) + else: + all_pairs = list(combinations(sim_idx, 2)) - # First, we identify pairs of replicas with overlapping ranges - swappables = [i for i in all_pairs if set(state_ranges[i[0]]).intersection(set(state_ranges[i[1]])) != set()] # noqa: E501 + # First, we identify pairs of replicas with overlapping ranges + swappables = [i for i in all_pairs if set(state_ranges[i[0]]).intersection(set(state_ranges[i[1]])) != set()] # noqa: E501 - # Then, from these pairs, we exclude the ones whose the last sampled states are not present in both alchemical ranges # noqa: E501 - # In this case, U^i_n, U_^j_m, g^i_n, and g_^j_m are unknown and the acceptance cannot be calculated. - swappables = [i for i in swappables if states[i[0]] in state_ranges[i[1]] and states[i[1]] in state_ranges[i[0]]] # noqa: E501 + # Then, from these pairs, we exclude the ones whose the last sampled states are not present in both alchemical ranges # noqa: E501 + # In this case, U^i_n, U_^j_m, g^i_n, and g_^j_m are unknown and the acceptance cannot be calculated. + swappables = [i for i in swappables if states[i[0]] in state_ranges[i[1]] and states[i[1]] in state_ranges[i[0]]] # noqa: E501 - # Expand the definition of swappable pairs when add_swappables is specified - if add_swappables is not None: - all_paired_states = [[states[p[0]], states[p[1]]] for p in all_pairs] - for i in all_paired_states: - if i in add_swappables: - pair = all_pairs[all_paired_states.index(i)] - if pair not in swappables: - swappables.append(pair) + # Expand the definition of swappable pairs when add_swappables is specified + if add_swappables is not None: + all_paired_states = [[states[p[0]], states[p[1]]] for p in all_pairs] + for i in all_paired_states: + if i in add_swappables: + pair = all_pairs[all_paired_states.index(i)] + if pair not in swappables: + swappables.append(pair) - if neighbor_exchange is True: - swappables = [i for i in swappables if np.abs(i[0] - i[1]) == 1] + if neighbor_exchange is True: + swappables = [i for i in swappables if np.abs(i[0] - i[1]) == 1] return swappables @@ -884,7 +897,7 @@ def propose_swap(swappables): return swap - def get_swapping_pattern(self, dhdl_files, states): + def get_swapping_pattern(self, dhdl_files, states, iteration=None): """ Generates a list (:code:`swap_pattern`) that represents how the configurations should be swapped in the next iteration. The indices of the output list correspond to the simulation/replica indices, and the @@ -908,6 +921,9 @@ def get_swapping_pattern(self, dhdl_files, states): A list of last sampled states (in global indices) of ALL simulations. :code:`states[i]=j` means that the configuration in replica :code:`i` is at state :code:`j` at the time when the exchange is performed. This list can be generated :obj:`.extract_final_dhdl_info`. + iteration : int + The iteration number will determine which direction the swaps will be performed. This option is only + necessary when using the "forced_swap" proposal scheme. Returns ------- @@ -917,7 +933,10 @@ def get_swapping_pattern(self, dhdl_files, states): A list of tuples showing the accepted swaps. """ swap_list = [] - if self.proposal == 'exhaustive': + if self.proposal == 'forced_swap': + n_ex = int(np.floor(self.n_sim / 2)) # This is the maximum, not necessarily the number that will always be reached. # noqa + swap_index = [] + elif self.proposal == 'exhaustive': n_ex = int(np.floor(self.n_sim / 2)) # This is the maximum, not necessarily the number that will always be reached. # noqa n_ex_exhaustive = 0 # The actual number of swaps atttempted. else: @@ -935,7 +954,7 @@ def get_swapping_pattern(self, dhdl_files, states): swap_pattern = list(range(self.n_sim)) # Can be regarded as the indices of DHDL files/configurations state_ranges = copy.deepcopy(self.state_ranges) # states_copy = copy.deepcopy(states) # only for re-identifying swappable pairs given updated state_ranges --> was needed for the multiple exchange proposal scheme # noqa: E501 - swappables = ReplicaExchangeEE.identify_swappable_pairs(states, state_ranges, self.proposal == 'neighboring', self.add_swappables) # noqa: E501 + swappables = ReplicaExchangeEE.identify_swappable_pairs(states, state_ranges, self.proposal == 'neighboring', self.add_swappables, iteration) # noqa: E501 # Note that if there is only 1 swappable pair, then it will still be the only swappable pair # after an attempted swap is accepted. Therefore, there is no need to perform multiple swaps or re-identify @@ -947,7 +966,7 @@ def get_swapping_pattern(self, dhdl_files, states): print(f"Swappable pairs: {swappables}") for i in range(n_ex): # Update the list of swappable pairs starting from the 2nd attempted swap for the exhaustive swap method. - if self.proposal == 'exhaustive' and i >= 1: + if (self.proposal == 'exhaustive' or self.proposal == 'forced_swap') and i >= 1: # Note that this should be done regardless of the acceptance/rejection of the previously drawn pairs. # Also note that at this point, swap is still the last attempted swap. swappables = [i for i in swappables if set(i).intersection(set(swap)) == set()] # noqa: F821 @@ -963,7 +982,10 @@ def get_swapping_pattern(self, dhdl_files, states): if self.proposal == 'exhaustive': n_ex_exhaustive += 1 - swap = ReplicaExchangeEE.propose_swap(swappables) + if self.propoal == 'forced_swap': + swap = swappables[0] + else: + swap = ReplicaExchangeEE.propose_swap(swappables) print(f'\nProposed swap: {swap}') if swap == []: # the same as len(swappables) == 0, self.proposal must not be exhaustive if this line is reached. # noqa: E501 self.n_empty_swappable += 1 @@ -974,6 +996,10 @@ def get_swapping_pattern(self, dhdl_files, states): if self.verbose is True and self.proposal != 'exhaustive': print(f'A swap ({i + 1}/{n_ex}) is proposed between the configurations of Simulation {swap[0]} (state {states[swap[0]]}) and Simulation {swap[1]} (state {states[swap[1]]}) ...') # noqa: E501 + if self.proposal == 'forced_swap': + index = self._deter_swap_index(swap, dhdl_files, shifts, self.add_swappables) + swap_index.append(index) + if self.modify_coords_fn is not None: swap_bool = True # always accept the move else: @@ -1024,7 +1050,7 @@ def get_swapping_pattern(self, dhdl_files, states): for i in range(self.n_sim): self.rep_trajs[i].append(self.configs.index(i)) - return swap_pattern, swap_list + return swap_pattern, swap_list, swap_index def calc_prob_acc(self, swap, dhdl_files, states, shifts): """ @@ -1127,6 +1153,54 @@ def accept_or_reject(self, prob_acc): print(" Swap rejected! ") return swap_bool + def _deter_swap_index(self, swap, dhdl_files, add_swappables): + """ + Determine which frames in the trajectory are sampling compatible lambda states to engage in a swap + + Parameters + ---------- + swap : list + The simulations for which the swap is occuring + dhdl_files : list + A list of paths to the DHDL files. The indicies in the DHDL filenames should be in an ascending order, e.g. + :code:`[dhdl_0.xvg, dhdl_1.xvg, ..., dhdl_N.xvg]`. + add_swappables: list + A list of lists that additionally consider states (in global indices) that can be swapped. + For example, :code:`add_swappables=[[4, 5], [14, 15]]` means that if a replica samples state 4, + it can be swapped with another replica that samples state 5 and vice versa. The same logic applies + to states 14 and 15. This parameter is only relevant to MT-REXEE simulations. + + Returns + ------- + swap_bool : bool + A boolean variable indicating whether the swap should be accepted. + """ + # Determine possible lambda states that swap partner i can be in to allow a swap + swappable_global_states = [] + for swappable in add_swappables: + A, B = swappable + swappable_global_states.append(A) + swappable_global_states.append(B) + + swap_index = [] + for i in range(1): + n = swap[i] + # Determine all frames for which swap partner i is in those states + potential_swap_index = [] + headers = get_headers(dhdl_files[n]) + state_local = list(extract_dataframe(dhdl_files[i], headers=headers)['Thermodynamic state']) # local index for all states # noqa: E501 + for s, state in enumerate(state_local): + state_global = state + i * self.s # global index of the last state + if state_global in swappable_global_states: + potential_swap_index.append(s) + + # Select a random frame which is in the last 50% of the trajectory to have the swap occur + potential_swap_index = np.array(potential_swap_index) + potential_swap_index = potential_swap_index[potential_swap_index > (len(state_local)/2)] + swap_index.append(np.random.choice(potential_swap_index)) + + return swap_index + def get_averaged_weights(self, log_files): """ For each replica, calculates the averaged weights (and the associated error) from the time series From e86ce0efd778d9644d404c6afd5b89971d183016 Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Wed, 11 Dec 2024 10:44:06 -0700 Subject: [PATCH 02/32] Update proposal options --- ensemble_md/replica_exchange_EE.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ensemble_md/replica_exchange_EE.py b/ensemble_md/replica_exchange_EE.py index 843dd14..a44aea3 100644 --- a/ensemble_md/replica_exchange_EE.py +++ b/ensemble_md/replica_exchange_EE.py @@ -197,7 +197,7 @@ def set_params(self, analysis): # Step 4: Check if the parameters in the YAML file are well-defined if self.proposal not in [None, 'single', 'neighboring', 'exhaustive', 'forced_swap']: # deprecated option: multiple # noqa: E501 - raise ParameterError("The specified proposal scheme is not available. Available options include 'single', 'neighboring', and 'exhaustive'.") # noqa: E501 + raise ParameterError("The specified proposal scheme is not available. Available options include 'single', 'neighboring', 'exhaustive', and 'forced_swap.") # noqa: E501 if self.df_method not in [None, 'TI', 'BAR', 'MBAR']: raise ParameterError("The specified free energy estimator is not available. Available options include 'TI', 'BAR', and 'MBAR'.") # noqa: E501 From c186287686df52ea8f5685b120018ad2fd51fc33 Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Wed, 11 Dec 2024 10:53:26 -0700 Subject: [PATCH 03/32] fix error --- ensemble_md/replica_exchange_EE.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ensemble_md/replica_exchange_EE.py b/ensemble_md/replica_exchange_EE.py index a44aea3..2b61299 100644 --- a/ensemble_md/replica_exchange_EE.py +++ b/ensemble_md/replica_exchange_EE.py @@ -790,7 +790,6 @@ def extract_final_log_info(self, log_files): return wl_delta, weights, counts - @staticmethod def identify_swappable_pairs(self, states, state_ranges, neighbor_exchange, add_swappables=None, iteration=None): """ Identifies swappable pairs. By definition, a pair of simulation is considered swappable only if From 1dfc70d8f813ca8167ae0d8bd744ccbadaf247af Mon Sep 17 00:00:00 2001 From: Anika Date: Wed, 11 Dec 2024 12:09:37 -0700 Subject: [PATCH 04/32] fix errors --- ensemble_md/cli/run_REXEE.py | 2 +- ensemble_md/replica_exchange_EE.py | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/ensemble_md/cli/run_REXEE.py b/ensemble_md/cli/run_REXEE.py index 435b38c..b595f8c 100644 --- a/ensemble_md/cli/run_REXEE.py +++ b/ensemble_md/cli/run_REXEE.py @@ -173,7 +173,7 @@ def main(): states = copy.deepcopy(states_) weights = copy.deepcopy(weights_) counts = copy.deepcopy(counts_) - swap_pattern, swap_list = REXEE.get_swapping_pattern(dhdl_files, states_) # swap_list will only be used for modify_coords # noqa: E501 + swap_pattern, swap_list = REXEE.get_swapping_pattern(dhdl_files, states_, i) # swap_list will only be used for modify_coords # noqa: E501 # 3-3. Perform weight correction/weight combination if wl_delta != [None for i in range(REXEE.n_sim)]: # weight-updating diff --git a/ensemble_md/replica_exchange_EE.py b/ensemble_md/replica_exchange_EE.py index a44aea3..81fd1d1 100644 --- a/ensemble_md/replica_exchange_EE.py +++ b/ensemble_md/replica_exchange_EE.py @@ -791,7 +791,7 @@ def extract_final_log_info(self, log_files): return wl_delta, weights, counts @staticmethod - def identify_swappable_pairs(self, states, state_ranges, neighbor_exchange, add_swappables=None, iteration=None): + def identify_swappable_pairs(states, state_ranges, neighbor_exchange, forced_swap, add_swappables=None, iteration=None): """ Identifies swappable pairs. By definition, a pair of simulation is considered swappable only if their last sampled states are in the alchemical ranges of both simulations. This is required @@ -841,15 +841,16 @@ def identify_swappable_pairs(self, states, state_ranges, neighbor_exchange, add_ """ n_sim = len(states) sim_idx = list(range(n_sim)) - if self.proposal == 'forced_swap': + if forced_swap is True: if iteration % 2 == 0: # Swap up for self.n_sim - 1 swaps swappables = [] - for n in np.arange(0, self.n_sim-2, 2): + for n in np.arange(0, n_sim-2, 2): swappables.append([n, n+1]) else: # and then swap down for self.n_sim - 1 swaps and repeat swappables = [] - for n in np.arange(1, self.n_sim-2, 2): + for n in np.arange(1, n_sim-2, 2): swappables.append([n, n+1]) + print(f'swappables: {swappables}') else: all_pairs = list(combinations(sim_idx, 2)) @@ -954,7 +955,7 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): swap_pattern = list(range(self.n_sim)) # Can be regarded as the indices of DHDL files/configurations state_ranges = copy.deepcopy(self.state_ranges) # states_copy = copy.deepcopy(states) # only for re-identifying swappable pairs given updated state_ranges --> was needed for the multiple exchange proposal scheme # noqa: E501 - swappables = ReplicaExchangeEE.identify_swappable_pairs(states, state_ranges, self.proposal == 'neighboring', self.add_swappables, iteration) # noqa: E501 + swappables = ReplicaExchangeEE.identify_swappable_pairs(states, state_ranges, self.proposal == 'neighboring', self.proposal == 'forced_swap', self.add_swappables, iteration) # noqa: E501 # Note that if there is only 1 swappable pair, then it will still be the only swappable pair # after an attempted swap is accepted. Therefore, there is no need to perform multiple swaps or re-identify @@ -963,7 +964,6 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): if n_ex > 1: n_ex = 1 # n_ex is set back to 1 since there is only 1 swappable pair. - print(f"Swappable pairs: {swappables}") for i in range(n_ex): # Update the list of swappable pairs starting from the 2nd attempted swap for the exhaustive swap method. if (self.proposal == 'exhaustive' or self.proposal == 'forced_swap') and i >= 1: @@ -982,7 +982,7 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): if self.proposal == 'exhaustive': n_ex_exhaustive += 1 - if self.propoal == 'forced_swap': + if self.proposal == 'forced_swap': swap = swappables[0] else: swap = ReplicaExchangeEE.propose_swap(swappables) @@ -997,7 +997,7 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): print(f'A swap ({i + 1}/{n_ex}) is proposed between the configurations of Simulation {swap[0]} (state {states[swap[0]]}) and Simulation {swap[1]} (state {states[swap[1]]}) ...') # noqa: E501 if self.proposal == 'forced_swap': - index = self._deter_swap_index(swap, dhdl_files, shifts, self.add_swappables) + index = self._deter_swap_index(swap, dhdl_files, self.add_swappables) swap_index.append(index) if self.modify_coords_fn is not None: @@ -1181,6 +1181,7 @@ def _deter_swap_index(self, swap, dhdl_files, add_swappables): A, B = swappable swappable_global_states.append(A) swappable_global_states.append(B) + print(swappable_global_states) swap_index = [] for i in range(1): From b9de8d8ff1abef792501685ce51bb00579a8705a Mon Sep 17 00:00:00 2001 From: Anika Date: Mon, 6 Jan 2025 13:26:47 -0700 Subject: [PATCH 05/32] Add forced_random --- ensemble_md/cli/run_REXEE.py | 33 ++++---- ensemble_md/replica_exchange_EE.py | 125 ++++++++++++++++++----------- 2 files changed, 93 insertions(+), 65 deletions(-) diff --git a/ensemble_md/cli/run_REXEE.py b/ensemble_md/cli/run_REXEE.py index b595f8c..b64fda0 100644 --- a/ensemble_md/cli/run_REXEE.py +++ b/ensemble_md/cli/run_REXEE.py @@ -138,7 +138,6 @@ def main(): REXEE.g_vecs = [list(i) for i in np.load(args.g_vecs)] if REXEE.fixed_weights is not True and os.path.isfile(args.equil) is True: REXEE.equil = np.load(args.equil) - print(REXEE.equil) else: start_idx = None @@ -173,7 +172,8 @@ def main(): states = copy.deepcopy(states_) weights = copy.deepcopy(weights_) counts = copy.deepcopy(counts_) - swap_pattern, swap_list = REXEE.get_swapping_pattern(dhdl_files, states_, i) # swap_list will only be used for modify_coords # noqa: E501 + swap_pattern, swap_list, swap_index, states = REXEE.get_swapping_pattern(dhdl_files, states_, i) # swap_list will only be used for modify_coords # noqa: E501 + print(f'swap pattern: {swap_pattern}') # 3-3. Perform weight correction/weight combination if wl_delta != [None for i in range(REXEE.n_sim)]: # weight-updating @@ -305,20 +305,21 @@ def main(): try: if rank == 0: for j in range(len(swap_list)): - print('\nModifying the coordinates of the following output GRO files ...') - # gro_1 and gro_2 are the simlation outputs (that we want to back up) and the inputs to modify_coords # noqa: E501 - gro_1 = f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout.gro' - gro_2 = f'{REXEE.working_dir}/sim_{swap_list[j][1]}/iteration_{i-1}/confout.gro' - print(f' - {gro_1}\n - {gro_2}') - - # Now we rename gro_1 and gro_2 to back them up - gro_1_backup = gro_1.split('.gro')[0] + '_backup.gro' - gro_2_backup = gro_2.split('.gro')[0] + '_backup.gro' - os.rename(gro_1, gro_1_backup) - os.rename(gro_2, gro_2_backup) - - # Here we input gro_1_backup and gro_2_backup and modify_coords_fn will save the modified gro files as gro_1 and gro_2 # noqa: E501 - REXEE.modify_coords_fn(gro_1_backup, gro_2_backup) # the order should not matter + if not os.path.exists(f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout_backup.gro') and not os.path.exists(f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout_backup.gro'): + print('\nModifying the coordinates of the following output GRO files ...') + # gro_1 and gro_2 are the simlation outputs (that we want to back up) and the inputs to modify_coords # noqa: E501 + gro_1 = f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout.gro' + gro_2 = f'{REXEE.working_dir}/sim_{swap_list[j][1]}/iteration_{i-1}/confout.gro' + print(f' - {gro_1}\n - {gro_2}') + + # Now we rename gro_1 and gro_2 to back them up + gro_1_backup = gro_1.split('.gro')[0] + '_backup.gro' + gro_2_backup = gro_2.split('.gro')[0] + '_backup.gro' + os.rename(gro_1, gro_1_backup) + os.rename(gro_2, gro_2_backup) + + # Here we input gro_1_backup and gro_2_backup and modify_coords_fn will save the modified gro files as gro_1 and gro_2 # noqa: E501 + REXEE.modify_coords_fn(gro_1_backup, gro_2_backup, swap_index[j]) # the order should not matter except Exception: print('\n--------------------------------------------------------------------------\n') print(f'\nAn error occurred on rank 0:\n{traceback.format_exc()}') diff --git a/ensemble_md/replica_exchange_EE.py b/ensemble_md/replica_exchange_EE.py index 81fd1d1..46817c8 100644 --- a/ensemble_md/replica_exchange_EE.py +++ b/ensemble_md/replica_exchange_EE.py @@ -196,8 +196,8 @@ def set_params(self, analysis): self.warnings.append(f'Warning: Parameter "{i}" specified in the input YAML file is not recognizable.') # Step 4: Check if the parameters in the YAML file are well-defined - if self.proposal not in [None, 'single', 'neighboring', 'exhaustive', 'forced_swap']: # deprecated option: multiple # noqa: E501 - raise ParameterError("The specified proposal scheme is not available. Available options include 'single', 'neighboring', 'exhaustive', and 'forced_swap.") # noqa: E501 + if self.proposal not in [None, 'single', 'neighboring', 'exhaustive', 'forced_swap', 'forced_random']: # deprecated option: multiple # noqa: E501 + raise ParameterError("The specified proposal scheme is not available. Available options include 'single', 'neighboring', 'exhaustive', 'forced_swap', 'forced_random'.") # noqa: E501 if self.df_method not in [None, 'TI', 'BAR', 'MBAR']: raise ParameterError("The specified free energy estimator is not available. Available options include 'TI', 'BAR', and 'MBAR'.") # noqa: E501 @@ -790,8 +790,7 @@ def extract_final_log_info(self, log_files): return wl_delta, weights, counts - @staticmethod - def identify_swappable_pairs(states, state_ranges, neighbor_exchange, forced_swap, add_swappables=None, iteration=None): + def identify_swappable_pairs(self, states, state_ranges, dhdl_files, iteration=None): # noqa: E501 """ Identifies swappable pairs. By definition, a pair of simulation is considered swappable only if their last sampled states are in the alchemical ranges of both simulations. This is required @@ -808,13 +807,6 @@ def identify_swappable_pairs(states, state_ranges, neighbor_exchange, forced_swa A list of global state indices for all replicas. The input list can be a list updated by :obj:`.get_swapping_pattern`, especially in the case where there is a need to re-identify the swappable pairs after an attempted swap is accepted. - neighbor_exchange : bool - Whether to exchange only between neighboring replicas. - add_swappables: list - A list of lists that additionally consider states (in global indices) that can be swapped. - For example, :code:`add_swappables=[[4, 5], [14, 15]]` means that if a replica samples state 4, - it can be swapped with another replica that samples state 5 and vice versa. The same logic applies - to states 14 and 15. This parameter is only relevant to MT-REXEE simulations. iteration : int The iteration number will determine which direction the swaps will be performed. This option is only necessary when using the "forced_swap" proposal scheme. @@ -841,16 +833,33 @@ def identify_swappable_pairs(states, state_ranges, neighbor_exchange, forced_swa """ n_sim = len(states) sim_idx = list(range(n_sim)) - if forced_swap is True: + states_for_swap = [] + if self.proposal == 'forced_swap': + potential_swappables = [] if iteration % 2 == 0: # Swap up for self.n_sim - 1 swaps - swappables = [] for n in np.arange(0, n_sim-2, 2): - swappables.append([n, n+1]) + potential_swappables.append([n, n+1]) else: # and then swap down for self.n_sim - 1 swaps and repeat - swappables = [] - for n in np.arange(1, n_sim-2, 2): - swappables.append([n, n+1]) - print(f'swappables: {swappables}') + for n in np.arange(1, n_sim-1, 2): + potential_swappables.append([n, n+1]) + swap_index, swappables = [], [] + for swap in potential_swappables: + index, state = self._deter_swap_index(swap, dhdl_files, self.add_swappables) + if len(index) == 2: + swap_index.append(index) + swappables.append(swap) + states_for_swap.append(state) + elif self.proposal == 'forced_random': + potential_swappables = [] + for n in np.arange(0, n_sim-1,1): + potential_swappables.append([n, n+1]) + swap_index, swappables = [], [] + for swap in potential_swappables: + index, state = self._deter_swap_index(swap, dhdl_files, self.add_swappables) + if len(index) == 2: + swap_index.append(index) + swappables.append(swap) + states_for_swap.append(state) else: all_pairs = list(combinations(sim_idx, 2)) @@ -862,18 +871,19 @@ def identify_swappable_pairs(states, state_ranges, neighbor_exchange, forced_swa swappables = [i for i in swappables if states[i[0]] in state_ranges[i[1]] and states[i[1]] in state_ranges[i[0]]] # noqa: E501 # Expand the definition of swappable pairs when add_swappables is specified - if add_swappables is not None: + if self.add_swappables is not None: all_paired_states = [[states[p[0]], states[p[1]]] for p in all_pairs] for i in all_paired_states: - if i in add_swappables: + if i in self.add_swappables: pair = all_pairs[all_paired_states.index(i)] if pair not in swappables: swappables.append(pair) - if neighbor_exchange is True: + if self.proposal == 'neighboring': swappables = [i for i in swappables if np.abs(i[0] - i[1]) == 1] + swap_index = [] - return swappables + return swappables, swap_index, states_for_swap @staticmethod def propose_swap(swappables): @@ -937,6 +947,10 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): if self.proposal == 'forced_swap': n_ex = int(np.floor(self.n_sim / 2)) # This is the maximum, not necessarily the number that will always be reached. # noqa swap_index = [] + elif self.proposal == 'forced_random': + swap_index = [] + n_ex = int(np.floor(self.n_sim / 2)) # This is the maximum, not necessarily the number that will always be reached. # noqa + n_ex_FR = 0 elif self.proposal == 'exhaustive': n_ex = int(np.floor(self.n_sim / 2)) # This is the maximum, not necessarily the number that will always be reached. # noqa n_ex_exhaustive = 0 # The actual number of swaps atttempted. @@ -955,7 +969,7 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): swap_pattern = list(range(self.n_sim)) # Can be regarded as the indices of DHDL files/configurations state_ranges = copy.deepcopy(self.state_ranges) # states_copy = copy.deepcopy(states) # only for re-identifying swappable pairs given updated state_ranges --> was needed for the multiple exchange proposal scheme # noqa: E501 - swappables = ReplicaExchangeEE.identify_swappable_pairs(states, state_ranges, self.proposal == 'neighboring', self.proposal == 'forced_swap', self.add_swappables, iteration) # noqa: E501 + swappables, swap_index, states_for_swap = self.identify_swappable_pairs(states, state_ranges, dhdl_files, iteration) # noqa: E501 # Note that if there is only 1 swappable pair, then it will still be the only swappable pair # after an attempted swap is accepted. Therefore, there is no need to perform multiple swaps or re-identify @@ -963,16 +977,18 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): if len(swappables) == 1: if n_ex > 1: n_ex = 1 # n_ex is set back to 1 since there is only 1 swappable pair. - + + states_modified = states + swap_index_accept = [] for i in range(n_ex): # Update the list of swappable pairs starting from the 2nd attempted swap for the exhaustive swap method. - if (self.proposal == 'exhaustive' or self.proposal == 'forced_swap') and i >= 1: + if (self.proposal == 'exhaustive' or self.proposal == 'forced_swap' or self.proposal == 'forced_random') and i >= 1: # Note that this should be done regardless of the acceptance/rejection of the previously drawn pairs. # Also note that at this point, swap is still the last attempted swap. swappables = [i for i in swappables if set(i).intersection(set(swap)) == set()] # noqa: F821 print(f'\nRemaining swappable pairs: {swappables}') - if len(swappables) == 0 and self.proposal == 'exhaustive': + if len(swappables) == 0 and (self.proposal == 'exhaustive' or self.proposal == 'forced_swap' or self.proposal == 'forced_random'): # This should only happen when the method of exhaustive swaps is used. if i == 0: self.n_empty_swappable += 1 @@ -981,11 +997,14 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): else: if self.proposal == 'exhaustive': n_ex_exhaustive += 1 + if self.proposal == 'forced_random': + n_ex_FR += 1 if self.proposal == 'forced_swap': swap = swappables[0] else: swap = ReplicaExchangeEE.propose_swap(swappables) + print(f'\nProposed swap: {swap}') if swap == []: # the same as len(swappables) == 0, self.proposal must not be exhaustive if this line is reached. # noqa: E501 self.n_empty_swappable += 1 @@ -993,12 +1012,9 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): break # no need to re-identify swappable pairs and draw new samples else: self.n_swap_attempts += 1 - if self.verbose is True and self.proposal != 'exhaustive': + if self.verbose is True and self.proposal != 'exhaustive' and self.proposal != 'forced_swap' and self.proposal != 'forced_random': print(f'A swap ({i + 1}/{n_ex}) is proposed between the configurations of Simulation {swap[0]} (state {states[swap[0]]}) and Simulation {swap[1]} (state {states[swap[1]]}) ...') # noqa: E501 - if self.proposal == 'forced_swap': - index = self._deter_swap_index(swap, dhdl_files, self.add_swappables) - swap_index.append(index) if self.modify_coords_fn is not None: swap_bool = True # always accept the move @@ -1019,6 +1035,13 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): if swap_bool is True: swap_list.append(swap) + if self.proposal == "forced_swap": + swap_index_accept.append(swap_index[i]) + states_modified[swap[0]] = states_for_swap[i][0] + states_modified[swap[1]] = states_for_swap[i][1] + else: + swap_index_accept.append([-1, -1]) + # Determine which # The assignments need to be done at the same time in just one line. # states[swap[0]], states[swap[1]] = states[swap[1]], states[swap[0]] # weights[swap[0]], weights[swap[1]] = weights[swap[1]], weights[swap[0]] @@ -1050,7 +1073,7 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): for i in range(self.n_sim): self.rep_trajs[i].append(self.configs.index(i)) - return swap_pattern, swap_list, swap_index + return swap_pattern, swap_list, swap_index_accept, states_modified def calc_prob_acc(self, swap, dhdl_files, states, shifts): """ @@ -1176,31 +1199,35 @@ def _deter_swap_index(self, swap, dhdl_files, add_swappables): A boolean variable indicating whether the swap should be accepted. """ # Determine possible lambda states that swap partner i can be in to allow a swap - swappable_global_states = [] + swappable_global_states, swap_state = [], [] for swappable in add_swappables: A, B = swappable - swappable_global_states.append(A) - swappable_global_states.append(B) - print(swappable_global_states) - + if (A >= (swap[0] * self.s) and A < ((swap[0] + 1) * self.s) and B >= (swap[1] * self.s) and B < ((swap[1] + 1) * self.s)) or (B >= (swap[0] * self.s) and B < ((swap[0] + 1) * self.s) and A >= (swap[1] * self.s) and A < ((swap[1] + 1) * self.s)): + swappable_global_states.append(A) + swappable_global_states.append(B) + convert_to_frames = int(self.template["nstxout"]/self.template["nstdhdl"]) swap_index = [] - for i in range(1): + for i in range(2): n = swap[i] # Determine all frames for which swap partner i is in those states - potential_swap_index = [] + potential_swap_index, state_global_list = [], [] headers = get_headers(dhdl_files[n]) - state_local = list(extract_dataframe(dhdl_files[i], headers=headers)['Thermodynamic state']) # local index for all states # noqa: E501 - for s, state in enumerate(state_local): - state_global = state + i * self.s # global index of the last state + state_local = list(extract_dataframe(dhdl_files[n], headers=headers)['Thermodynamic state']) # local index for all states # noqa: E501 + for s, state in enumerate(state_local[::convert_to_frames]): + state_global = state + (n * self.s) # global index of the last state if state_global in swappable_global_states: potential_swap_index.append(s) - + state_global_list.append(state_global) # Select a random frame which is in the last 50% of the trajectory to have the swap occur potential_swap_index = np.array(potential_swap_index) - potential_swap_index = potential_swap_index[potential_swap_index > (len(state_local)/2)] - swap_index.append(np.random.choice(potential_swap_index)) - - return swap_index + potential_swap_index = potential_swap_index[potential_swap_index > (len(state_local)/(2*convert_to_frames))] + if len(potential_swap_index) != 0: + index = np.random.choice(potential_swap_index) + swap_state.append(state_global_list[np.where(potential_swap_index == index)[0][0]]) + swap_index.append(index) + else: + break + return swap_index, swap_state def get_averaged_weights(self, log_files): """ @@ -1597,7 +1624,7 @@ def run_REXEE(self, n, swap_pattern=None): # rank 3 that has not been generated, which will lead to an I/O error. comm.barrier() - def default_coords_fn(self, molA_file_name, molB_file_name): + def default_coords_fn(self, molA_file_name, molB_file_name, swap_index): """ Swaps coordinates between two GRO files. @@ -1613,8 +1640,8 @@ def default_coords_fn(self, molA_file_name, molB_file_name): molB_dir = molB_file_name.rsplit('/', 1)[0] + '/' # Load trajectory trr for higher precison coordinates - molA = md.load_trr(f'{molA_dir}/traj.trr', top=molA_file_name).slice(-1) # Load last frame of trr trajectory - molB = md.load_trr(f'{molB_dir}/traj.trr', top=molB_file_name).slice(-1) + molA = md.load_trr(f'{molA_dir}/traj.trr', top=molA_file_name).slice(swap_index[0]) # Load last frame of trr trajectory + molB = md.load_trr(f'{molB_dir}/traj.trr', top=molB_file_name).slice(swap_index[1]) # Load the coordinate swapping map connection_map = pd.read_csv('residue_connect.csv') From 163d4f4d1a6a5ecefa9ab7c753cd7ebd7532fdbc Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Mon, 6 Jan 2025 13:37:24 -0700 Subject: [PATCH 06/32] Fix error in forced_random --- ensemble_md/replica_exchange_EE.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/ensemble_md/replica_exchange_EE.py b/ensemble_md/replica_exchange_EE.py index 46817c8..65606fd 100644 --- a/ensemble_md/replica_exchange_EE.py +++ b/ensemble_md/replica_exchange_EE.py @@ -833,7 +833,7 @@ def identify_swappable_pairs(self, states, state_ranges, dhdl_files, iteration=N """ n_sim = len(states) sim_idx = list(range(n_sim)) - states_for_swap = [] + states_for_swap = {} if self.proposal == 'forced_swap': potential_swappables = [] if iteration % 2 == 0: # Swap up for self.n_sim - 1 swaps @@ -842,24 +842,26 @@ def identify_swappable_pairs(self, states, state_ranges, dhdl_files, iteration=N else: # and then swap down for self.n_sim - 1 swaps and repeat for n in np.arange(1, n_sim-1, 2): potential_swappables.append([n, n+1]) - swap_index, swappables = [], [] + swappables = [] + swap_index = {} for swap in potential_swappables: index, state = self._deter_swap_index(swap, dhdl_files, self.add_swappables) if len(index) == 2: - swap_index.append(index) + swap_index[swap] = index swappables.append(swap) - states_for_swap.append(state) + states_for_swap[swap] = state elif self.proposal == 'forced_random': potential_swappables = [] for n in np.arange(0, n_sim-1,1): potential_swappables.append([n, n+1]) - swap_index, swappables = [], [] + swappables = [] + swap_index = {} for swap in potential_swappables: index, state = self._deter_swap_index(swap, dhdl_files, self.add_swappables) if len(index) == 2: - swap_index.append(index) + swap_index[swap] = index swappables.append(swap) - states_for_swap.append(state) + states_for_swap[swap] = state else: all_pairs = list(combinations(sim_idx, 2)) @@ -1036,9 +1038,10 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): if swap_bool is True: swap_list.append(swap) if self.proposal == "forced_swap": - swap_index_accept.append(swap_index[i]) - states_modified[swap[0]] = states_for_swap[i][0] - states_modified[swap[1]] = states_for_swap[i][1] + swap_index_accept.append(swap_index[swap]) + states_i = states_for_swap[swap] + states_modified[swap[0]] = states_i[0] + states_modified[swap[1]] = states_i[1] else: swap_index_accept.append([-1, -1]) # Determine which From 81f8482a78339083a71f20921fe56e5380a0d3fe Mon Sep 17 00:00:00 2001 From: Anika Date: Thu, 9 Jan 2025 10:31:53 -0700 Subject: [PATCH 07/32] Fix forced_random l state assignment --- ensemble_md/replica_exchange_EE.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/ensemble_md/replica_exchange_EE.py b/ensemble_md/replica_exchange_EE.py index 65606fd..60b3076 100644 --- a/ensemble_md/replica_exchange_EE.py +++ b/ensemble_md/replica_exchange_EE.py @@ -833,7 +833,7 @@ def identify_swappable_pairs(self, states, state_ranges, dhdl_files, iteration=N """ n_sim = len(states) sim_idx = list(range(n_sim)) - states_for_swap = {} + states_for_swap = [] if self.proposal == 'forced_swap': potential_swappables = [] if iteration % 2 == 0: # Swap up for self.n_sim - 1 swaps @@ -842,26 +842,24 @@ def identify_swappable_pairs(self, states, state_ranges, dhdl_files, iteration=N else: # and then swap down for self.n_sim - 1 swaps and repeat for n in np.arange(1, n_sim-1, 2): potential_swappables.append([n, n+1]) - swappables = [] - swap_index = {} + swappables, swap_index = [], [] for swap in potential_swappables: index, state = self._deter_swap_index(swap, dhdl_files, self.add_swappables) if len(index) == 2: - swap_index[swap] = index + swap_index.append(index) swappables.append(swap) - states_for_swap[swap] = state + states_for_swap.append(state) elif self.proposal == 'forced_random': potential_swappables = [] for n in np.arange(0, n_sim-1,1): potential_swappables.append([n, n+1]) - swappables = [] - swap_index = {} + swappables, swap_index = [], [] for swap in potential_swappables: index, state = self._deter_swap_index(swap, dhdl_files, self.add_swappables) if len(index) == 2: - swap_index[swap] = index + swap_index.append(index) swappables.append(swap) - states_for_swap[swap] = state + states_for_swap.append(state) else: all_pairs = list(combinations(sim_idx, 2)) @@ -972,6 +970,7 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): state_ranges = copy.deepcopy(self.state_ranges) # states_copy = copy.deepcopy(states) # only for re-identifying swappable pairs given updated state_ranges --> was needed for the multiple exchange proposal scheme # noqa: E501 swappables, swap_index, states_for_swap = self.identify_swappable_pairs(states, state_ranges, dhdl_files, iteration) # noqa: E501 + all_swappables = swappables.copy() # Note that if there is only 1 swappable pair, then it will still be the only swappable pair # after an attempted swap is accepted. Therefore, there is no need to perform multiple swaps or re-identify @@ -1037,11 +1036,13 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): if swap_bool is True: swap_list.append(swap) - if self.proposal == "forced_swap": - swap_index_accept.append(swap_index[swap]) - states_i = states_for_swap[swap] - states_modified[swap[0]] = states_i[0] - states_modified[swap[1]] = states_i[1] + if self.proposal == "forced_swap" or self.proposal == "forced_random": + for p, p_swap in enumerate(all_swappables): + if p_swap == swap: + break + swap_index_accept.append(swap_index[p]) + states_modified[swap[0]] = states_for_swap[p][0] + states_modified[swap[1]] = states_for_swap[p][1] else: swap_index_accept.append([-1, -1]) # Determine which From db5f1e01c4eb78e7d61ce6ce675a8e9f0cb91779 Mon Sep 17 00:00:00 2001 From: Anika Date: Thu, 9 Jan 2025 10:53:01 -0700 Subject: [PATCH 08/32] Fix linting --- ensemble_md/cli/run_REXEE.py | 4 ++-- ensemble_md/replica_exchange_EE.py | 19 +++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/ensemble_md/cli/run_REXEE.py b/ensemble_md/cli/run_REXEE.py index b64fda0..0abebda 100644 --- a/ensemble_md/cli/run_REXEE.py +++ b/ensemble_md/cli/run_REXEE.py @@ -305,7 +305,7 @@ def main(): try: if rank == 0: for j in range(len(swap_list)): - if not os.path.exists(f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout_backup.gro') and not os.path.exists(f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout_backup.gro'): + if not os.path.exists(f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout_backup.gro') and not os.path.exists(f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout_backup.gro'): # noqa: E501 print('\nModifying the coordinates of the following output GRO files ...') # gro_1 and gro_2 are the simlation outputs (that we want to back up) and the inputs to modify_coords # noqa: E501 gro_1 = f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout.gro' @@ -319,7 +319,7 @@ def main(): os.rename(gro_2, gro_2_backup) # Here we input gro_1_backup and gro_2_backup and modify_coords_fn will save the modified gro files as gro_1 and gro_2 # noqa: E501 - REXEE.modify_coords_fn(gro_1_backup, gro_2_backup, swap_index[j]) # the order should not matter + REXEE.modify_coords_fn(gro_1_backup, gro_2_backup, swap_index[j]) # the order should not matter # noqa: E501 except Exception: print('\n--------------------------------------------------------------------------\n') print(f'\nAn error occurred on rank 0:\n{traceback.format_exc()}') diff --git a/ensemble_md/replica_exchange_EE.py b/ensemble_md/replica_exchange_EE.py index 60b3076..95840b1 100644 --- a/ensemble_md/replica_exchange_EE.py +++ b/ensemble_md/replica_exchange_EE.py @@ -851,7 +851,7 @@ def identify_swappable_pairs(self, states, state_ranges, dhdl_files, iteration=N states_for_swap.append(state) elif self.proposal == 'forced_random': potential_swappables = [] - for n in np.arange(0, n_sim-1,1): + for n in np.arange(0, n_sim-1, 1): potential_swappables.append([n, n+1]) swappables, swap_index = [], [] for swap in potential_swappables: @@ -978,18 +978,18 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): if len(swappables) == 1: if n_ex > 1: n_ex = 1 # n_ex is set back to 1 since there is only 1 swappable pair. - + states_modified = states swap_index_accept = [] for i in range(n_ex): # Update the list of swappable pairs starting from the 2nd attempted swap for the exhaustive swap method. - if (self.proposal == 'exhaustive' or self.proposal == 'forced_swap' or self.proposal == 'forced_random') and i >= 1: + if (self.proposal == 'exhaustive' or self.proposal == 'forced_swap' or self.proposal == 'forced_random') and i >= 1: # noqa: E501 # Note that this should be done regardless of the acceptance/rejection of the previously drawn pairs. # Also note that at this point, swap is still the last attempted swap. swappables = [i for i in swappables if set(i).intersection(set(swap)) == set()] # noqa: F821 print(f'\nRemaining swappable pairs: {swappables}') - if len(swappables) == 0 and (self.proposal == 'exhaustive' or self.proposal == 'forced_swap' or self.proposal == 'forced_random'): + if len(swappables) == 0 and (self.proposal == 'exhaustive' or self.proposal == 'forced_swap' or self.proposal == 'forced_random'): # noqa: E501 # This should only happen when the method of exhaustive swaps is used. if i == 0: self.n_empty_swappable += 1 @@ -1005,7 +1005,7 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): swap = swappables[0] else: swap = ReplicaExchangeEE.propose_swap(swappables) - + print(f'\nProposed swap: {swap}') if swap == []: # the same as len(swappables) == 0, self.proposal must not be exhaustive if this line is reached. # noqa: E501 self.n_empty_swappable += 1 @@ -1013,10 +1013,9 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): break # no need to re-identify swappable pairs and draw new samples else: self.n_swap_attempts += 1 - if self.verbose is True and self.proposal != 'exhaustive' and self.proposal != 'forced_swap' and self.proposal != 'forced_random': + if self.verbose is True and self.proposal != 'exhaustive' and self.proposal != 'forced_swap' and self.proposal != 'forced_random': # noqa: E501 print(f'A swap ({i + 1}/{n_ex}) is proposed between the configurations of Simulation {swap[0]} (state {states[swap[0]]}) and Simulation {swap[1]} (state {states[swap[1]]}) ...') # noqa: E501 - if self.modify_coords_fn is not None: swap_bool = True # always accept the move else: @@ -1206,7 +1205,7 @@ def _deter_swap_index(self, swap, dhdl_files, add_swappables): swappable_global_states, swap_state = [], [] for swappable in add_swappables: A, B = swappable - if (A >= (swap[0] * self.s) and A < ((swap[0] + 1) * self.s) and B >= (swap[1] * self.s) and B < ((swap[1] + 1) * self.s)) or (B >= (swap[0] * self.s) and B < ((swap[0] + 1) * self.s) and A >= (swap[1] * self.s) and A < ((swap[1] + 1) * self.s)): + if (A >= (swap[0] * self.s) and A < ((swap[0] + 1) * self.s) and B >= (swap[1] * self.s) and B < ((swap[1] + 1) * self.s)) or (B >= (swap[0] * self.s) and B < ((swap[0] + 1) * self.s) and A >= (swap[1] * self.s) and A < ((swap[1] + 1) * self.s)): # noqa: E501 swappable_global_states.append(A) swappable_global_states.append(B) convert_to_frames = int(self.template["nstxout"]/self.template["nstdhdl"]) @@ -1224,7 +1223,7 @@ def _deter_swap_index(self, swap, dhdl_files, add_swappables): state_global_list.append(state_global) # Select a random frame which is in the last 50% of the trajectory to have the swap occur potential_swap_index = np.array(potential_swap_index) - potential_swap_index = potential_swap_index[potential_swap_index > (len(state_local)/(2*convert_to_frames))] + potential_swap_index = potential_swap_index[potential_swap_index > (len(state_local)/(2*convert_to_frames))] # noqa: E501 if len(potential_swap_index) != 0: index = np.random.choice(potential_swap_index) swap_state.append(state_global_list[np.where(potential_swap_index == index)[0][0]]) @@ -1644,7 +1643,7 @@ def default_coords_fn(self, molA_file_name, molB_file_name, swap_index): molB_dir = molB_file_name.rsplit('/', 1)[0] + '/' # Load trajectory trr for higher precison coordinates - molA = md.load_trr(f'{molA_dir}/traj.trr', top=molA_file_name).slice(swap_index[0]) # Load last frame of trr trajectory + molA = md.load_trr(f'{molA_dir}/traj.trr', top=molA_file_name).slice(swap_index[0]) # Load last frame of trr trajectory # noqa: E501 molB = md.load_trr(f'{molB_dir}/traj.trr', top=molB_file_name).slice(swap_index[1]) # Load the coordinate swapping map From f305e035b128c6d6b82280fc4d87715dca628735 Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Tue, 14 Jan 2025 13:34:52 -0700 Subject: [PATCH 09/32] Fix tests --- ensemble_md/tests/test_replica_exchange_EE.py | 52 ++++++++++++++----- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/ensemble_md/tests/test_replica_exchange_EE.py b/ensemble_md/tests/test_replica_exchange_EE.py index 3bbe89f..ce7fc50 100644 --- a/ensemble_md/tests/test_replica_exchange_EE.py +++ b/ensemble_md/tests/test_replica_exchange_EE.py @@ -90,7 +90,7 @@ def test_set_params_error(self, params_dict): params_dict['n_sim'] = 4 # so params_dict can be read without failing in the assertions below # 2. Available options - check_param_error(params_dict, 'proposal', "The specified proposal scheme is not available. Available options include 'single', 'neighboring', and 'exhaustive'.", 'cool', 'exhaustive') # noqa: E501 + check_param_error(params_dict, 'proposal', "The specified proposal scheme is not available. Available options include 'single', 'neighboring', 'exhaustive', 'forced_swap', 'forced_random'.", 'cool', 'exhaustive') # noqa: E501 check_param_error(params_dict, 'df_method', "The specified free energy estimator is not available. Available options include 'TI', 'BAR', and 'MBAR'.") # noqa: E501 check_param_error(params_dict, 'err_method', "The specified method for error estimation is not available. Available options include 'propagate', and 'bootstrap'.") # noqa: E501 @@ -652,22 +652,29 @@ def test_identify_swappable_pairs(self, params_dict): REXEE = get_REXEE_instance(params_dict) REXEE.state_ranges = [list(range(i, i + 5)) for i in range(REXEE.n_sim)] # 5 states per replica states = [4, 2, 2, 7] # This would lead to the swappables: [(0, 1), (0, 2), (1, 2)] in the standard case + dhdl_files = [os.path.join(input_path, f"dhdl/dhdl_{i}.xvg") for i in range(4)] # Case 1: Any case that is not neighboring swap has the same definition for the swappable pairs - swappables = REXEE.identify_swappable_pairs(states, REXEE.state_ranges, REXEE.proposal == 'neighboring') + swappables, swap_index, states_for_swap = REXEE.identify_swappable_pairs(states, REXEE.state_ranges, dhdl_files) assert swappables == [(0, 1), (0, 2), (1, 2)] + assert swap_index == [] + assert states_for_swap == [] # Case 2: Neighboring exchange REXEE.proposal = 'neighboring' - swappables = REXEE.identify_swappable_pairs(states, REXEE.state_ranges, REXEE.proposal == 'neighboring') + swappables, swap_index, states_for_swap = REXEE.identify_swappable_pairs(states, REXEE.state_ranges, dhdl_files) assert swappables == [(0, 1), (1, 2)] + assert swap_index == [] + assert states_for_swap == [] # Case 3: Non-neighboring exchange, with add_swappables REXEE.proposal = 'exhaustive' REXEE.add_swappables = [[3, 7], [4, 7]] states = [4, 3, 2, 7] # Without add_swappables, the swappables would be [(0, 1), (0, 2), (1, 2)] - swappables = REXEE.identify_swappable_pairs(states, REXEE.state_ranges, REXEE.proposal == 'neighboring', REXEE.add_swappables) # noqa: E501 + swappables, swap_index, states_for_swap = REXEE.identify_swappable_pairs(states, REXEE.state_ranges, dhdl_files) # noqa: E501 assert swappables == [(0, 1), (0, 2), (1, 2), (0, 3), (1, 3)] + assert swap_index == [] + assert states_for_swap == [] def test_propose_swap(self, params_dict): random.seed(0) @@ -687,24 +694,29 @@ def test_get_swapping_pattern(self, params_dict): REXEE.verbose = False states = [0, 6, 7, 8] # No swappable pairs f = copy.deepcopy(dhdl_files) - pattern, swap_list = REXEE.get_swapping_pattern(f, states) + pattern, swap_list, swap_index_accept, states_modified = REXEE.get_swapping_pattern(f, states) assert REXEE.n_empty_swappable == 1 assert REXEE.n_swap_attempts == 0 assert REXEE.n_rejected == 0 assert pattern == [0, 1, 2, 3] assert swap_list == [] + assert swap_index_accept == [] + assert states_modified == states # Test 2: Empty swap list, neighboring proposal REXEE = get_REXEE_instance(params_dict) REXEE.proposal = 'neighboring' # n_ex will be set to 1 automatically. states = [0, 6, 7, 8] # No swappable pairs f = copy.deepcopy(dhdl_files) - pattern, swap_list = REXEE.get_swapping_pattern(f, states) + pattern, swap_list, swap_index_accept, states_modified = REXEE.get_swapping_pattern(f, states) + print(f'2: {swap_index_accept} {states_modified}') assert REXEE.n_empty_swappable == 1 assert REXEE.n_swap_attempts == 0 assert REXEE.n_rejected == 0 assert pattern == [0, 1, 2, 3] assert swap_list == [] + assert swap_index_accept == [] + assert states_modified == states # Test 3: Single swap (proposal = 'single') random.seed(0) @@ -713,11 +725,13 @@ def test_get_swapping_pattern(self, params_dict): REXEE.proposal = 'single' # n_ex will be set to 1 automatically. states = [5, 2, 2, 8] # swappable pairs: [(0, 1), (0, 2), (1, 2)], swap = (1, 2), accept f = copy.deepcopy(dhdl_files) - pattern, swap_list = REXEE.get_swapping_pattern(f, states) + pattern, swap_list, swap_index_accept, states_modified = REXEE.get_swapping_pattern(f, states) assert REXEE.n_swap_attempts == 1 assert REXEE.n_rejected == 0 assert pattern == [0, 2, 1, 3] assert swap_list == [(1, 2)] + assert swap_index_accept == [[-1, -1]] + assert states_modified == states # Test 4: Neighboring swap random.seed(0) @@ -725,11 +739,13 @@ def test_get_swapping_pattern(self, params_dict): REXEE.proposal = 'neighboring' # n_ex will be set to 1 automatically. states = [5, 2, 2, 8] # swappable pairs: [(0, 1), (0, 2), (1, 2)], swap = (1, 2), accept f = copy.deepcopy(dhdl_files) - pattern, swap_list = REXEE.get_swapping_pattern(f, states) + pattern, swap_list, swap_index_accept, states_modified = REXEE.get_swapping_pattern(f, states) assert REXEE.n_swap_attempts == 1 assert REXEE.n_rejected == 0 assert pattern == [0, 2, 1, 3] assert swap_list == [(1, 2)] + assert swap_index_accept == [[-1, -1]] + assert states_modified == states # Test 5: Exhaustive swaps that end up in a single swap random.seed(0) @@ -737,11 +753,13 @@ def test_get_swapping_pattern(self, params_dict): REXEE.proposal = 'exhaustive' states = [5, 2, 2, 8] # swappable pairs: [(0, 1), (0, 2), (1, 2)], swap = (1, 2), accept f = copy.deepcopy(dhdl_files) - pattern, swap_list = REXEE.get_swapping_pattern(f, states) + pattern, swap_list, swap_index_accept, states_modified = REXEE.get_swapping_pattern(f, states) assert REXEE.n_swap_attempts == 1 assert REXEE.n_rejected == 0 assert pattern == [0, 2, 1, 3] assert swap_list == [(1, 2)] + assert swap_index_accept == [[-1, -1]] + assert states_modified == states # Test 6: Exhaustive swaps that involve multiple attempted swaps random.seed(0) @@ -749,11 +767,13 @@ def test_get_swapping_pattern(self, params_dict): REXEE.proposal = 'exhaustive' states = [4, 2, 4, 3] # swappable pairs: [(0, 1), (0, 2), (0, 3), (1, 2), (2, 3)]; swap 1: (2, 3), accepted; swap 2: (0, 1), accept # noqa: E501 f = copy.deepcopy(dhdl_files) - pattern, swap_list = REXEE.get_swapping_pattern(f, states) + pattern, swap_list, swap_index_accept, states_modified = REXEE.get_swapping_pattern(f, states) assert REXEE.n_swap_attempts == 2 # \Delta is negative for both swaps -> both accepted assert REXEE.n_rejected == 0 assert pattern == [1, 0, 3, 2] assert swap_list == [(2, 3), (0, 1)] + assert swap_index_accept == [[-1, -1], [-1, -1]] + assert states_modified == states # Test 7: REXEE.proposal is set to exhaustive but there is only one swappable pair anyway. random.seed(0) @@ -761,11 +781,13 @@ def test_get_swapping_pattern(self, params_dict): REXEE.proposal = 'exhaustive' states = [0, 2, 2, 8] # swappable pair: [(1, 2)], swap: (1, 2), accept f = copy.deepcopy(dhdl_files) - pattern, swap_list = REXEE.get_swapping_pattern(f, states) + pattern, swap_list, swap_index_accept, states_modified = REXEE.get_swapping_pattern(f, states) assert REXEE.n_swap_attempts == 1 assert REXEE.n_rejected == 0 assert pattern == [0, 2, 1, 3] assert swap_list == [(1, 2)] + assert swap_index_accept == [[-1, -1]] + assert states_modified == states # Test 8: modify_coords_fn is not None, so swap_bool is always True random.seed(0) @@ -773,11 +795,13 @@ def test_get_swapping_pattern(self, params_dict): REXEE.modify_coords_fn = 'Cool' states = [5, 2, 2, 8] # swappable pairs: [(0, 1), (0, 2), (1, 2)], swap = (1, 2), accept f = copy.deepcopy(dhdl_files) - pattern, swap_list = REXEE.get_swapping_pattern(f, states) + pattern, swap_list, swap_index_accept, states_modified = REXEE.get_swapping_pattern(f, states) assert REXEE.n_swap_attempts == 1 assert REXEE.n_rejected == 0 assert pattern == [0, 2, 1, 3] assert swap_list == [(1, 2)] + assert swap_index_accept == [[-1, -1]] + assert states_modified == states def test_calc_prob_acc(self, capfd, params_dict): # k = 1.380649e-23; NA = 6.0221408e23; T = 298; kT = k * NA * T / 1000 = 2.4777098766670016 @@ -900,7 +924,7 @@ def test_default_coords_fn(self, params_dict): REXEE = get_REXEE_instance(params_dict) os.system(f'cp {input_path}/coord_swap/residue_connect.csv .') os.system(f'cp {input_path}/coord_swap/residue_swap_map.csv .') - REXEE.default_coords_fn(f'{input_path}/coord_swap/sim_A/confout_backup.gro', f'{input_path}/coord_swap/sim_B/confout_backup.gro') # noqa: E501 + REXEE.default_coords_fn(f'{input_path}/coord_swap/sim_A/confout_backup.gro', f'{input_path}/coord_swap/sim_B/confout_backup.gro', [-1, -1]) # noqa: E501 true_output_A = open(f'{input_path}/coord_swap/output_A.gro', 'r').readlines() test_output_A = open(f'{input_path}/coord_swap/sim_B/confout.gro', 'r').readlines() @@ -914,7 +938,7 @@ def test_default_coords_fn(self, params_dict): os.system(f'cp {input_path}/coord_swap/residue_connect_alt.csv residue_connect.csv') os.system(f'cp {input_path}/coord_swap/residue_swap_map_alt.csv residue_swap_map.csv') - REXEE.default_coords_fn(f'{input_path}/coord_swap/sim_C/confout_backup.gro', f'{input_path}/coord_swap/sim_D/confout_backup.gro') # noqa: E501 + REXEE.default_coords_fn(f'{input_path}/coord_swap/sim_C/confout_backup.gro', f'{input_path}/coord_swap/sim_D/confout_backup.gro', [-1, -1]) # noqa: E501 true_output_C = open(f'{input_path}/coord_swap/output_C.gro', 'r').readlines() test_output_C = open(f'{input_path}/coord_swap/sim_D/confout.gro', 'r').readlines() From cb8a343d869f35e7cd1f600fb5af79a015c6ee91 Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Tue, 14 Jan 2025 13:35:47 -0700 Subject: [PATCH 10/32] Fix linting --- ensemble_md/tests/test_replica_exchange_EE.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ensemble_md/tests/test_replica_exchange_EE.py b/ensemble_md/tests/test_replica_exchange_EE.py index ce7fc50..c2af9b8 100644 --- a/ensemble_md/tests/test_replica_exchange_EE.py +++ b/ensemble_md/tests/test_replica_exchange_EE.py @@ -655,14 +655,14 @@ def test_identify_swappable_pairs(self, params_dict): dhdl_files = [os.path.join(input_path, f"dhdl/dhdl_{i}.xvg") for i in range(4)] # Case 1: Any case that is not neighboring swap has the same definition for the swappable pairs - swappables, swap_index, states_for_swap = REXEE.identify_swappable_pairs(states, REXEE.state_ranges, dhdl_files) + swappables, swap_index, states_for_swap = REXEE.identify_swappable_pairs(states, REXEE.state_ranges, dhdl_files) # noqa: E501 assert swappables == [(0, 1), (0, 2), (1, 2)] assert swap_index == [] assert states_for_swap == [] # Case 2: Neighboring exchange REXEE.proposal = 'neighboring' - swappables, swap_index, states_for_swap = REXEE.identify_swappable_pairs(states, REXEE.state_ranges, dhdl_files) + swappables, swap_index, states_for_swap = REXEE.identify_swappable_pairs(states, REXEE.state_ranges, dhdl_files) # noqa: E501 assert swappables == [(0, 1), (1, 2)] assert swap_index == [] assert states_for_swap == [] From ab9f3947fce147a3e1297e9e8e4154efdd13c545 Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Fri, 17 Jan 2025 13:49:32 -0700 Subject: [PATCH 11/32] Add MT-REXEE analysis functions --- ensemble_md/analysis/analyze_traj.py | 86 ++++++++++++++++++++++++++++ ensemble_md/cli/analyze_REXEE.py | 12 ++++ ensemble_md/utils/gmx_parser.py | 18 ++++++ 3 files changed, 116 insertions(+) diff --git a/ensemble_md/analysis/analyze_traj.py b/ensemble_md/analysis/analyze_traj.py index 45af0bb..8285862 100644 --- a/ensemble_md/analysis/analyze_traj.py +++ b/ensemble_md/analysis/analyze_traj.py @@ -1330,3 +1330,89 @@ def get_delta_w_updates(log_file, plot=False): plt.savefig('delta_w_updates.png', dpi=600) return t_updates, delta_w_updates, equil + + +def end_states_only_traj(working_dir, n_sim, n_iter, l0_states, l1_states, swap_rep_pattern, ps_per_frame): + import pandas as pd + import os + import mdtraj as md + + # Determine how many end states are present, which simulations and lambdas those end states correspond to + state_name = ['A'] + considered_swaps = [[0,0]] + cat = ord('A') + 1 + for swap in swap_rep_pattern: + part_1, part_2 = swap + if part_1 in considered_swaps and part_2 in considered_swaps: + continue + elif part_1 in considered_swaps: + index = considered_swaps.index(part_1) + state_name.append(state_name[index]) + considered_swaps.append(part_2) + elif part_2 in considered_swaps: + index = considered_swaps.index(part_2) + state_name.append(state_name[index]) + considered_swaps.append(part_1) + else: + state_name.append(chr(cat)) + state_name.append(chr(cat)) + considered_swaps.append(part_1) + considered_swaps.append(part_2) + cat += 1 + for i in range(n_sim): + for j in [0, 1]: + if [i, j] not in considered_swaps: + state_name.append(chr(cat)) + considered_swaps.append([i, j]) + cat += 1 + + # Determine which frames correspond to which end states + state_frame_df = pd.DataFrame() + for n in range(n_sim): + for i in range(n_iter): + l0_frame, l1_frame = [],[] + dhdl_file = open(f'{working_dir}/sim_{n}/iteration_{i}/dhdl.xvg', 'r').readlines() + start = True + for line in dhdl_file: + split_line = line.split(' ') + while '' in split_line: + split_line.remove('') + if '#' not in split_line[0] and '@' not in split_line[0]: + time = float(split_line[0]) + if start: + start_time = time + start = False + state = float(split_line[1]) + if time%ps_per_frame == 0: + if state in l0_states: + l0_frame.append(int((time-start_time)/ps_per_frame)) + elif state in l1_states: + l1_frame.append(int((time-start_time)/ps_per_frame)) + if len(l0_frame) != 0: + df_0 = pd.DataFrame({'Sim': n, 'Iteration': i, 'Frame': l0_frame, 'Lambda': 0}) + state_frame_df = pd.concat([state_frame_df, df_0]) + if len(l1_frame) != 0: + df_1 = pd.DataFrame({'Sim': n, 'Iteration': i, 'Frame': l1_frame, 'Lambda': 1}) + state_frame_df = pd.concat([state_frame_df, df_1]) + + # Concatenate all frames from each set of trajectories for each end state + unique_states = list(set(state_name)) + for state in unique_states: + indices = [i for i, value in enumerate(state_name) if value == state] + for i, index in enumerate(indices): + rep, l = considered_swaps[index] + started = False + if os.path.exists(f'{working_dir}/sim_{rep}/iteration_0/confout_backup.gro'): + name = 'confout_backup' + else: + name = 'confout' + for iteration in range(n_iter): + frames_select = state_frame_df[(state_frame_df['Sim'] == rep) & (state_frame_df['Iteration'] == iteration) & (state_frame_df['Lambda'] == l)]['Frame'].to_numpy() + if len(frames_select) != 0: + if not started: + traj = md.load(f'{working_dir}/sim_{rep}/iteration_{iteration}/traj.trr', top=f'{working_dir}/sim_{rep}/iteration_0/{name}.gro') + started = True + else: + traj_add = md.load(f'{working_dir}/sim_{rep}/iteration_{iteration}/traj.trr', top=f'{working_dir}/sim_{rep}/iteration_0/{name}.gro') + traj = md.join(traj, traj_add) + traj.save_xtc(f'{working_dir}/analysis/{state}_{rep}.xtc') diff --git a/ensemble_md/cli/analyze_REXEE.py b/ensemble_md/cli/analyze_REXEE.py index 62dfbd6..37e0df3 100644 --- a/ensemble_md/cli/analyze_REXEE.py +++ b/ensemble_md/cli/analyze_REXEE.py @@ -25,6 +25,7 @@ warnings.simplefilter(action='ignore', category=UserWarning) from ensemble_md.utils import utils # noqa: E402 +from ensemble_md.utils import gmx_parser from ensemble_md.analysis import analyze_traj # noqa: E402 from ensemble_md.analysis import analyze_matrix # noqa: E402 from ensemble_md.analysis import msm_analysis # noqa: E402 @@ -454,6 +455,17 @@ def main(): for i in range(REXEE.n_sim): print(f'RMSE of the free energy profile for alchemical range {i} (states {REXEE.state_ranges[i][0]} to {REXEE.state_ranges[i][-1]}): {rmse_list[i]:.2f} kT') # noqa: E501 + # Section 5. Process trajecotries for MT-REXEE + if REXEE.modify_coords is not None: + # Section 5.1. Create end-state trajecotries for each simulation + l0, l1, ps_per_frame = gmx_parser.get_end_states(f'{REXEE.working_dir}/sim_0/iteration_0/expanded.mdp') + n_sim, n_iter = np.shape(rep_trajs) + if REXEE.swap_rep_pattern is None: + raise Exception('MT-REXEE trajectory analysis requires swap_rep_pattern to be defined') + analyze_traj.end_states_only_traj(REXEE.working_dir, n_sim, n_iter, l0, l1, REXEE.swap_rep_pattern, ps_per_frame) + + # Section 5.2. Create concatenated trajectories for each individual simulation + # Section 4. Calculate the time spent in GROMACS (This could take a while.) t_wall_tot, t_sync, _ = utils.analyze_REXEE_time() print(f'\nTotal wall time GROMACS spent to finish all iterations: {utils.format_time(t_wall_tot)}') diff --git a/ensemble_md/utils/gmx_parser.py b/ensemble_md/utils/gmx_parser.py index 4ee8eb3..256e791 100644 --- a/ensemble_md/utils/gmx_parser.py +++ b/ensemble_md/utils/gmx_parser.py @@ -444,3 +444,21 @@ def deter_atom_order(mol_file, resname): break return atom_order + +def get_end_states(mdp_path): + mdp = MDP(mdp_path) + end_0, end_1 = [], [] + coul_lambda = mdp['coul_lambdas'] + vdw_lambda = mdp['vdw_lambdas'] + n = 0 + for vdw, coul in zip(coul_lambda, vdw_lambda): + if vdw == 0.0 and coul == 0.0: + end_0.append(n) + elif vdw == 1.0 and coul == 1.0: + end_1.append(n) + n += 1 + dt = mdp['dt'] + steps_per_frame = mdp['nstxout'] + ps_per_frame = dt*steps_per_frame + + return end_0, end_1, ps_per_frame \ No newline at end of file From 6f8477915ff3056480b51ea17bbdd8e5de1b0a26 Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Fri, 17 Jan 2025 14:54:14 -0700 Subject: [PATCH 12/32] Fix linting --- ensemble_md/analysis/analyze_traj.py | 18 +++++++++--------- ensemble_md/cli/analyze_REXEE.py | 4 ++-- ensemble_md/utils/coordinate_swap.py | 6 +++--- ensemble_md/utils/gmx_parser.py | 3 ++- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/ensemble_md/analysis/analyze_traj.py b/ensemble_md/analysis/analyze_traj.py index 8285862..48362df 100644 --- a/ensemble_md/analysis/analyze_traj.py +++ b/ensemble_md/analysis/analyze_traj.py @@ -1339,7 +1339,7 @@ def end_states_only_traj(working_dir, n_sim, n_iter, l0_states, l1_states, swap_ # Determine how many end states are present, which simulations and lambdas those end states correspond to state_name = ['A'] - considered_swaps = [[0,0]] + considered_swaps = [[0, 0]] cat = ord('A') + 1 for swap in swap_rep_pattern: part_1, part_2 = swap @@ -1370,7 +1370,7 @@ def end_states_only_traj(working_dir, n_sim, n_iter, l0_states, l1_states, swap_ state_frame_df = pd.DataFrame() for n in range(n_sim): for i in range(n_iter): - l0_frame, l1_frame = [],[] + l0_frame, l1_frame = [], [] dhdl_file = open(f'{working_dir}/sim_{n}/iteration_{i}/dhdl.xvg', 'r').readlines() start = True for line in dhdl_file: @@ -1383,14 +1383,14 @@ def end_states_only_traj(working_dir, n_sim, n_iter, l0_states, l1_states, swap_ start_time = time start = False state = float(split_line[1]) - if time%ps_per_frame == 0: + if time % ps_per_frame == 0: if state in l0_states: l0_frame.append(int((time-start_time)/ps_per_frame)) elif state in l1_states: l1_frame.append(int((time-start_time)/ps_per_frame)) if len(l0_frame) != 0: - df_0 = pd.DataFrame({'Sim': n, 'Iteration': i, 'Frame': l0_frame, 'Lambda': 0}) - state_frame_df = pd.concat([state_frame_df, df_0]) + df_0 = pd.DataFrame({'Sim': n, 'Iteration': i, 'Frame': l0_frame, 'Lambda': 0}) + state_frame_df = pd.concat([state_frame_df, df_0]) if len(l1_frame) != 0: df_1 = pd.DataFrame({'Sim': n, 'Iteration': i, 'Frame': l1_frame, 'Lambda': 1}) state_frame_df = pd.concat([state_frame_df, df_1]) @@ -1400,19 +1400,19 @@ def end_states_only_traj(working_dir, n_sim, n_iter, l0_states, l1_states, swap_ for state in unique_states: indices = [i for i, value in enumerate(state_name) if value == state] for i, index in enumerate(indices): - rep, l = considered_swaps[index] + rep, lambda_rep = considered_swaps[index] started = False if os.path.exists(f'{working_dir}/sim_{rep}/iteration_0/confout_backup.gro'): name = 'confout_backup' else: name = 'confout' for iteration in range(n_iter): - frames_select = state_frame_df[(state_frame_df['Sim'] == rep) & (state_frame_df['Iteration'] == iteration) & (state_frame_df['Lambda'] == l)]['Frame'].to_numpy() + frames_select = state_frame_df[(state_frame_df['Sim'] == rep) & (state_frame_df['Iteration'] == iteration) & (state_frame_df['Lambda'] == lambda_rep)]['Frame'].to_numpy() # noqa: E501 if len(frames_select) != 0: if not started: - traj = md.load(f'{working_dir}/sim_{rep}/iteration_{iteration}/traj.trr', top=f'{working_dir}/sim_{rep}/iteration_0/{name}.gro') + traj = md.load(f'{working_dir}/sim_{rep}/iteration_{iteration}/traj.trr', top=f'{working_dir}/sim_{rep}/iteration_0/{name}.gro') # noqa: E501 started = True else: - traj_add = md.load(f'{working_dir}/sim_{rep}/iteration_{iteration}/traj.trr', top=f'{working_dir}/sim_{rep}/iteration_0/{name}.gro') + traj_add = md.load(f'{working_dir}/sim_{rep}/iteration_{iteration}/traj.trr', top=f'{working_dir}/sim_{rep}/iteration_0/{name}.gro') # noqa: E501 traj = md.join(traj, traj_add) traj.save_xtc(f'{working_dir}/analysis/{state}_{rep}.xtc') diff --git a/ensemble_md/cli/analyze_REXEE.py b/ensemble_md/cli/analyze_REXEE.py index 37e0df3..4cf23e4 100644 --- a/ensemble_md/cli/analyze_REXEE.py +++ b/ensemble_md/cli/analyze_REXEE.py @@ -25,7 +25,7 @@ warnings.simplefilter(action='ignore', category=UserWarning) from ensemble_md.utils import utils # noqa: E402 -from ensemble_md.utils import gmx_parser +from ensemble_md.utils import gmx_parser # noqa: E402 from ensemble_md.analysis import analyze_traj # noqa: E402 from ensemble_md.analysis import analyze_matrix # noqa: E402 from ensemble_md.analysis import msm_analysis # noqa: E402 @@ -462,7 +462,7 @@ def main(): n_sim, n_iter = np.shape(rep_trajs) if REXEE.swap_rep_pattern is None: raise Exception('MT-REXEE trajectory analysis requires swap_rep_pattern to be defined') - analyze_traj.end_states_only_traj(REXEE.working_dir, n_sim, n_iter, l0, l1, REXEE.swap_rep_pattern, ps_per_frame) + analyze_traj.end_states_only_traj(REXEE.working_dir, n_sim, n_iter, l0, l1, REXEE.swap_rep_pattern, ps_per_frame) # noqa: E501 # Section 5.2. Create concatenated trajectories for each individual simulation diff --git a/ensemble_md/utils/coordinate_swap.py b/ensemble_md/utils/coordinate_swap.py index 599eb0d..e8d0a7c 100644 --- a/ensemble_md/utils/coordinate_swap.py +++ b/ensemble_md/utils/coordinate_swap.py @@ -365,9 +365,9 @@ def get_miss_coord(mol_align, mol_ref, name_align, name_ref, df_atom_swap, dir, """ # Create a new column for coordinates if one does not exist if 'X Coordinates' not in df_atom_swap.columns: - df_atom_swap['X Coordinates'] = np.NaN - df_atom_swap['Y Coordinates'] = np.NaN - df_atom_swap['Z Coordinates'] = np.NaN + df_atom_swap['X Coordinates'] = np.nan + df_atom_swap['Y Coordinates'] = np.nan + df_atom_swap['Z Coordinates'] = np.nan if len(df_swap.index) == 0: return df_atom_swap diff --git a/ensemble_md/utils/gmx_parser.py b/ensemble_md/utils/gmx_parser.py index 256e791..a279e71 100644 --- a/ensemble_md/utils/gmx_parser.py +++ b/ensemble_md/utils/gmx_parser.py @@ -445,6 +445,7 @@ def deter_atom_order(mol_file, resname): return atom_order + def get_end_states(mdp_path): mdp = MDP(mdp_path) end_0, end_1 = [], [] @@ -461,4 +462,4 @@ def get_end_states(mdp_path): steps_per_frame = mdp['nstxout'] ps_per_frame = dt*steps_per_frame - return end_0, end_1, ps_per_frame \ No newline at end of file + return end_0, end_1, ps_per_frame From 1e9655cdb9f54b173d7b3dac73854d2cf382cea7 Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Fri, 17 Jan 2025 16:05:56 -0700 Subject: [PATCH 13/32] Save transition matrix to array and fix file paths --- ensemble_md/analysis/analyze_traj.py | 9 ++++++++- ensemble_md/cli/analyze_REXEE.py | 7 ++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/ensemble_md/analysis/analyze_traj.py b/ensemble_md/analysis/analyze_traj.py index 48362df..70e50d9 100644 --- a/ensemble_md/analysis/analyze_traj.py +++ b/ensemble_md/analysis/analyze_traj.py @@ -539,7 +539,14 @@ def plot_state_hist(trajs, state_ranges, fig_name, stack=True, figsize=None, pre hist, bins = np.histogram(traj, bins=np.arange(lower_bound, upper_bound + 1, 1)) hist_data.append(hist) if save_hist is True: - np.save('hist_data.npy', hist_data) + if len(fig_name.split('/')) > 1: + dir_list = [] + for i in fig_name.split('/')[:-1]: + dir_list.append(i) + dir_path = ''.join(dir_list) + np.save(f'{dir_path}/hist_data.npy', hist_data) + else: + np.save('hist_data.npy', hist_data) # Use the same bins for all histograms bins = bins[:-1] # Remove the last bin edge because there are n+1 bin edges for n bins diff --git a/ensemble_md/cli/analyze_REXEE.py b/ensemble_md/cli/analyze_REXEE.py index 4cf23e4..9dcba2f 100644 --- a/ensemble_md/cli/analyze_REXEE.py +++ b/ensemble_md/cli/analyze_REXEE.py @@ -139,12 +139,13 @@ def main(): counts = [analyze_traj.traj2transmtx(rep_trajs[i], REXEE.n_sim, normalize=False) for i in range(len(rep_trajs))] reps_mtx = np.sum(counts, axis=0) # First sum up the counts. This should be symmetric if n_ex=1. Otherwise it might not be. # noqa: E501 reps_mtx /= np.sum(reps_mtx, axis=1)[:, None] # and then normalize each row + np.save(f'{args.dir}/reps_transmtx_allconfigs.npy', reps_mtx) analyze_matrix.plot_matrix(reps_mtx, f'{args.dir}/rep_transmtx_allconfigs.png') # 1-3. Calculate the spectral gap for the replica-space transition amtrix - print('1-3. Calculating the spectral gap of the replica-space transition matrix ...') - spectral_gap, spectral_gap_err, eig_vals = analyze_matrix.calc_spectral_gap(reps_mtx) - print(f'The spectral gap of the replica-space transition matrix: {spectral_gap:.3f}') +# print('1-3. Calculating the spectral gap of the replica-space transition matrix ...') +# spectral_gap, spectral_gap_err, eig_vals = analyze_matrix.calc_spectral_gap(reps_mtx) +# print(f'The spectral gap of the replica-space transition matrix: {spectral_gap:.3f}') # Section 2. Analysis based on transitions between states print('\n[ Section 2. Analysis based on transitions between states ]') From ff1129425bc122cf1224bf4c8f5670ec338b5719 Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Sun, 19 Jan 2025 06:10:39 -0700 Subject: [PATCH 14/32] Add forced-swap test --- .../tests/data/dhdl/forced-swap/dhdl_0.xvg | 238 ++++++++++++++++++ .../tests/data/dhdl/forced-swap/dhdl_1.xvg | 238 ++++++++++++++++++ .../tests/data/dhdl/forced-swap/dhdl_2.xvg | 238 ++++++++++++++++++ .../tests/data/dhdl/forced-swap/dhdl_3.xvg | 238 ++++++++++++++++++ ensemble_md/tests/test_replica_exchange_EE.py | 16 ++ 5 files changed, 968 insertions(+) create mode 100644 ensemble_md/tests/data/dhdl/forced-swap/dhdl_0.xvg create mode 100644 ensemble_md/tests/data/dhdl/forced-swap/dhdl_1.xvg create mode 100644 ensemble_md/tests/data/dhdl/forced-swap/dhdl_2.xvg create mode 100644 ensemble_md/tests/data/dhdl/forced-swap/dhdl_3.xvg diff --git a/ensemble_md/tests/data/dhdl/forced-swap/dhdl_0.xvg b/ensemble_md/tests/data/dhdl/forced-swap/dhdl_0.xvg new file mode 100644 index 0000000..d98bdc5 --- /dev/null +++ b/ensemble_md/tests/data/dhdl/forced-swap/dhdl_0.xvg @@ -0,0 +1,238 @@ +# This file was created Sun Jan 19 05:14:48 2025 +# Created by: +# :-) GROMACS - gmx mdrun, 2022.5-dev (-: +# +# Executable: /projects/anfr8476/pkgs/gromacs-2022.5-wl/bin/gmx +# Data prefix: /projects/anfr8476/pkgs/gromacs-2022.5-wl +# Working dir: /gpfs/alpine1/scratch/anfr8476/EEXE/test_forced_swap/small_mol/forced_random/solv/rep1/sim_0/iteration_0 +# Command line: +# gmx mdrun -s sys_EE.tpr -ntomp 6 -ntmpi 1 +# gmx mdrun is part of G R O M A C S: +# +# Great Red Owns Many ACres of Sand +# +@ title "dH/d\xl\f{} and \xD\f{}H" +@ xaxis label "Time (ps)" +@ yaxis label "dH/d\xl\f{} and \xD\f{}H (kJ/mol [\xl\f{}]\S-1\N)" +@TYPE xy +@ subtitle "T = 300 (K) " +@ view 0.15, 0.15, 0.75, 0.85 +@ legend on +@ legend box on +@ legend loctype view +@ legend 0.78, 0.8 +@ legend length 2 +@ s0 legend "Thermodynamic state" +@ s1 legend "Total Energy (kJ/mol)" +@ s2 legend "dH/d\xl\f{} coul-lambda = 0.0000" +@ s3 legend "dH/d\xl\f{} vdw-lambda = 0.0000" +@ s4 legend "dH/d\xl\f{} bonded-lambda = 0.0000" +@ s5 legend "\xD\f{}H \xl\f{} to (0.0000, 0.0000, 0.0000)" +@ s6 legend "\xD\f{}H \xl\f{} to (0.1000, 0.1000, 0.1000)" +@ s7 legend "\xD\f{}H \xl\f{} to (0.3000, 0.3000, 0.3000)" +@ s8 legend "\xD\f{}H \xl\f{} to (0.6000, 0.6000, 0.6000)" +@ s9 legend "\xD\f{}H \xl\f{} to (0.7000, 0.7000, 0.7000)" +@ s10 legend "\xD\f{}H \xl\f{} to (0.8500, 0.8500, 0.8500)" +@ s11 legend "\xD\f{}H \xl\f{} to (1.0000, 1.0000, 1.0000)" +@ s12 legend "pV (kJ/mol)" +0.0000 0 -22140.262 347.00287 -6.0445342 0.27468294 0.0000000 26.156472 56.833529 93.372082 116.35309 225.14500 2522.7879 1.2356462 +0.2000 0 -22098.219 427.54614 2.9169538 2.1202245 0.0000000 33.224477 73.962186 130.67853 167.05095 319.82370 2623.7639 1.2336415 +0.4000 0 -22124.039 181.84421 -11.380078 0.90858173 0.0000000 14.823468 35.388053 56.565810 64.398272 83.689728 135.82458 1.2384079 +0.6000 0 -22180.248 193.54037 -13.651375 1.4849931 0.0000000 15.826578 36.721663 49.058854 49.122481 45.941788 39.692037 1.2403417 +0.8000 0 -22173.670 278.82516 -9.3808460 1.1165063 0.0000000 23.147994 57.854214 128.09261 188.17207 500.61379 166968.11 1.2406895 +1.0000 0 -22146.637 191.24170 2.1709588 3.7599547 0.0000000 17.645594 44.733167 83.907514 106.42523 185.49341 647.41995 1.2416046 +1.2000 0 -22107.992 283.37582 7.1995611 3.3666420 0.0000000 24.142361 58.115812 116.25816 156.07672 323.58981 4184.0484 1.2395648 +1.4000 0 -22117.291 170.47070 -2.0250301 0.87817031 0.0000000 15.201767 38.331787 69.084436 85.437829 141.13277 438.30577 1.2369061 +1.6000 0 -22121.088 270.86703 -6.6573572 3.5801792 0.0000000 22.782531 52.414318 76.146095 82.410815 97.716635 151.61534 1.2404798 +1.8000 0 -22094.893 372.72525 -5.0162935 2.3256373 0.0000000 27.375150 58.759918 102.59763 131.44704 246.35756 1378.6509 1.2410387 +2.0000 0 -22129.520 321.16428 -2.0591712 8.1266413 0.0000000 25.823765 57.266510 92.071473 110.28366 184.77770 1051.5707 1.2412069 +2.2000 0 -22128.324 284.07239 -9.8285837 10.253619 0.0000000 23.553263 52.543370 71.261201 72.760918 71.021526 64.103570 1.2402484 +2.4000 0 -22131.396 243.27545 0.94861537 9.5620136 0.0000000 22.214717 54.419432 95.695209 117.50258 194.77038 752.09850 1.2425175 +2.6000 0 -22150.117 227.24770 -0.36753422 5.1872573 0.0000000 20.456494 50.933996 95.327537 122.93053 238.64222 2083.1740 1.2469435 +2.8000 0 -22191.703 283.12646 3.8526671 5.1858258 0.0000000 25.089621 60.424857 108.92434 138.85796 263.98700 1744.2276 1.2497563 +3.0000 0 -22278.043 300.58984 5.1458249 0.53568792 0.0000000 26.140165 62.358829 109.04066 133.59996 209.14800 496.36101 1.2512907 +3.2000 0 -22255.092 469.45172 3.5149097 2.2912402 0.0000000 36.898695 79.671094 123.38344 143.02974 200.58270 416.58465 1.2526252 +3.4000 0 -22278.922 261.07220 -0.52158111 8.5241461 0.0000000 23.191264 55.895887 97.918893 122.76502 234.66247 2651.6190 1.2557850 +3.6000 0 -22320.887 257.72876 -3.7893190 8.5310869 0.0000000 22.533433 53.449310 87.583527 103.17301 154.77599 455.44858 1.2526054 +3.8000 0 -22290.318 203.36914 -1.6783631 8.5693579 0.0000000 19.035406 48.812628 91.983874 116.69924 199.11383 570.80275 1.2531465 +4.0000 0 -22310.965 299.66745 -7.2152181 3.3267653 0.0000000 23.739190 52.447652 77.691953 87.289818 121.49329 350.43710 1.2551342 +4.2000 0 -22303.438 441.97769 -3.7868307 0.90856761 0.0000000 31.648619 64.629497 92.436926 103.04289 136.51765 290.88280 1.2554698 +4.4000 0 -22316.133 192.05457 -4.1805072 3.0385454 0.0000000 16.854833 40.739540 64.492847 73.448662 99.080113 196.66046 1.2529523 +4.6000 1 -22320.447 115.17644 20.792152 8.5604258 -14.868614 0.0000000 29.839578 113.69285 186.28936 500.12084 4040.9370 1.2527002 +4.8000 0 -22340.949 282.38464 0.81364453 2.6479387 0.0000000 23.932691 58.248841 117.17632 156.68419 297.51819 1164.5407 1.2513170 +5.0000 0 -22387.430 100.76828 -0.10960597 8.2239647 0.0000000 10.324453 29.596802 70.838482 99.886065 213.22392 1276.4578 1.2525116 +5.2000 1 -22362.334 78.555542 -6.7094150 4.2134418 -7.9703279 0.0000000 13.611097 30.840286 38.228152 58.922382 131.49050 1.2525780 +5.4000 1 -22427.438 129.65146 -12.500166 6.7520118 -14.176865 0.0000000 19.223005 32.294419 33.362381 32.343154 28.631938 1.2521027 +5.6000 0 -22446.531 307.76355 -13.693457 0.67357957 0.0000000 22.540768 46.227133 56.630455 54.893629 46.266264 24.497960 1.2505947 +5.8000 6 -22415.691 -187.10754 0.44660461 0.92059940 -21.531330 -3.0318740 16.848248 26.024608 24.763953 17.798168 0.0000000 1.2490736 +6.0000 5 -22323.723 28.806343 2.8496628 0.29347640 -20.392437 -18.148632 -13.651715 -6.7997225 -4.3019061 0.0000000 5.5727038 1.2495970 +6.2000 4 -22372.156 22.612877 -1.0449271 1.3006727 -19.487650 -16.102547 -9.9218638 -2.2874795 0.0000000 3.5894766 8.1444103 1.2483975 +6.4000 3 -22381.520 24.298363 6.4314780 2.2201977 -20.933920 -17.016261 -9.7569933 0.0000000 3.4498231 9.8049395 19.549113 1.2544328 +6.6000 4 -22316.457 23.257610 -9.5317154 0.28663290 -15.343378 -12.356489 -7.2252924 -1.4842592 0.0000000 1.9658192 3.8265006 1.2508248 +6.8000 4 -22233.625 24.993202 10.977043 0.42573416 -18.338494 -15.852124 -10.971439 -3.2614990 0.0000000 6.9193689 19.929638 1.2493517 +7.0000 3 -22261.293 25.643017 -7.6395645 8.4524498 -21.121723 -16.741581 -9.0583131 0.0000000 2.5854867 6.5399448 11.775880 1.2478917 +7.2000 4 -22250.363 21.610317 -4.8313551 0.56910533 -18.825202 -15.086222 -8.7499073 -1.8105190 0.0000000 2.5409336 5.3370772 1.2494786 +7.4000 5 -22236.113 13.046452 0.49406439 0.63884449 -21.739295 -17.395427 -10.388988 -3.5733195 -2.0437063 0.0000000 2.8253245 1.2551517 +7.6000 4 -22331.092 28.152779 -1.2958188 9.3234901 -19.948799 -17.735918 -12.371100 -3.4102498 0.0000000 6.2100649 15.625561 1.2546780 +7.8000 4 -22375.740 21.319111 -11.221223 6.6551895 -20.931177 -16.733264 -9.5795042 -1.8427797 0.0000000 2.1742781 3.8194386 1.2577437 +8.0000 5 -22414.025 -38.858269 -9.8535891 2.0340011 -29.309822 -17.998870 -2.8409772 5.4380673 4.6811689 0.0000000 -9.7325442 1.2570728 +8.2000 6 -22467.734 -404.34137 -10.018071 1.5833110 -18.948891 11.645585 38.565768 48.617243 45.912728 33.959395 0.0000000 1.2563243 +8.4000 6 -22417.566 -51.966751 -1.7853192 0.42501155 -20.080198 -11.098361 1.5051865 9.2047090 9.0303254 6.1812360 0.0000000 1.2589587 +8.6000 5 -22420.422 -1.1911469 15.619684 1.3968362 -29.186887 -23.204778 -13.682357 -4.5245377 -2.5058889 0.0000000 2.5599232 1.2585628 +8.8000 2 -22357.289 43.637451 0.26437867 4.8510442 -17.015228 -10.697095 0.0000000 14.292613 20.064455 32.939193 60.835097 1.2568903 +9.0000 1 -22273.566 38.797672 -5.8211193 9.0640898 -4.1685863 0.0000000 8.6698905 24.653597 32.270439 49.833947 88.784877 1.2582161 +9.2000 2 -22226.879 33.004536 1.2659233 5.2214656 -11.071069 -7.4991659 0.0000000 14.049096 20.626672 34.633122 58.983316 1.2572570 +9.4000 3 -22200.928 26.692928 33.949554 1.1447388 -25.784429 -22.236509 -14.650670 0.0000000 6.9163127 21.353076 44.972264 1.2584074 +9.6000 2 -22168.789 43.790615 -9.4392023 3.3164375 -13.869587 -8.7099022 0.0000000 8.8711220 10.990880 14.006384 18.130423 1.2579609 +9.8000 4 -22187.910 1.8717041 120.33966 8.1645212 -59.374189 -49.579032 -33.562318 -10.878187 0.0000000 29.430288 115.24951 1.2567711 +10.0000 0 -22225.838 294.99005 -5.3597603 1.1538022 0.0000000 22.809787 49.813044 78.183571 93.350425 161.29561 1069.4806 1.2579776 +10.2000 0 -22294.262 107.93524 -5.5084453 11.355924 0.0000000 10.572862 27.902584 50.191525 59.441223 81.632626 135.11689 1.2575432 +10.4000 1 -22227.562 124.29597 5.8692369 1.5070384 -14.773698 0.0000000 22.151916 50.322468 62.840411 93.538067 164.82691 1.2593921 +10.6000 0 -22237.885 282.40921 -8.5927925 2.6896074 0.0000000 21.004752 43.649414 57.520014 58.478574 55.900019 43.629426 1.2617834 +10.8000 0 -22145.008 145.46677 -10.543301 5.6274834 0.0000000 12.651459 30.997455 45.519896 47.650966 48.893764 48.511596 1.2637676 +11.0000 1 -22153.445 88.342239 5.6763105 9.7317820 -10.619352 0.0000000 20.533524 61.833801 87.690129 170.02167 517.67674 1.2639478 +11.2000 1 -22125.918 88.959084 2.8760347 1.5792353 -9.9689329 0.0000000 17.065174 45.863892 63.930130 130.00718 502.57648 1.2658527 +11.4000 1 -22060.734 84.938187 2.5655482 9.4164724 -10.191742 0.0000000 17.948031 45.069650 57.547892 87.006640 149.68733 1.2618484 +11.6000 1 -22031.703 68.982712 0.75882965 10.217326 -8.2831133 0.0000000 15.277229 40.638055 53.194255 84.651926 161.96052 1.2619021 +11.8000 0 -22048.566 217.32999 -7.1789455 2.4213483 0.0000000 18.690231 44.284311 63.229910 66.694843 73.766071 101.30746 1.2708489 +12.0000 0 -22009.350 470.22748 -3.3144011 5.8105640 0.0000000 32.535519 64.828859 93.674796 105.09488 139.25075 293.46642 1.2728976 +12.2000 0 -21988.025 393.58038 1.4040279 9.3361120 0.0000000 29.378825 63.507115 113.30098 143.97513 256.73328 1256.0881 1.2724149 +12.4000 0 -21965.545 80.854507 5.0199103 3.9324501 0.0000000 8.8463041 26.844145 68.598153 98.083297 206.84865 1010.9313 1.2712432 +12.6000 1 -21880.945 78.741089 17.409830 0.62270653 -9.7099395 0.0000000 20.199153 70.789947 110.47877 297.00182 13810.907 1.2699659 +12.8000 1 -21911.988 102.46066 1.8164549 1.6702181 -10.338903 0.0000000 23.397767 98.003230 168.28359 504.49191 5754.4089 1.2721552 +13.0000 1 -21850.777 60.606224 -6.1199021 2.8843386 -6.0057381 0.0000000 10.521562 24.535381 29.812593 40.350920 58.487091 1.2691746 +13.2000 1 -21820.471 152.85025 -12.817139 1.5718377 -16.468053 0.0000000 21.094482 31.393409 29.836165 22.533943 8.0717683 1.2692460 +13.4000 6 -21876.773 -250.15633 5.6443110 1.0618854 -23.021005 0.66791723 26.803965 37.805662 35.298024 24.525671 0.0000000 1.2670863 +13.6000 6 -21907.154 -99.563026 -7.6992044 1.0073003 -20.688778 -7.2908160 10.619195 19.835607 18.575227 12.338030 0.0000000 1.2671328 +13.8000 6 -21913.273 -150.77910 -3.1847277 0.61077344 -20.419980 -3.6722639 16.798572 26.343132 24.594430 16.686083 0.0000000 1.2660803 +14.0000 6 -21916.139 -91.989288 1.0890319 1.5986190 -22.940201 -10.980626 4.2266467 13.149469 12.948648 9.2867207 0.0000000 1.2642746 +14.2000 5 -21951.227 12.654305 28.604986 2.8767493 -31.668015 -26.971354 -18.767524 -8.8059180 -5.6180272 0.0000000 8.8726965 1.2658799 +14.4000 3 -21892.922 23.427944 12.679817 4.4139986 -23.403826 -19.108333 -11.221951 0.0000000 4.3933456 13.454720 30.363086 1.2678388 +14.6000 2 -21893.436 30.133842 -4.5075054 7.5467486 -8.4371765 -6.0906428 0.0000000 11.291449 15.995172 24.840284 37.729811 1.2664472 +14.8000 2 -21926.270 32.702377 27.760340 8.5129375 -17.395334 -12.096085 0.0000000 30.447500 50.178918 109.36740 316.15234 1.2665007 +15.0000 1 -21953.352 43.623474 0.82360226 8.5086145 -5.0289156 0.0000000 11.434487 35.441125 48.742544 83.858726 180.06054 1.2681137 +15.2000 2 -21988.588 33.641369 44.124168 2.0528738 -15.412164 -11.985001 0.0000000 44.638566 82.014212 236.47685 2644.4608 1.2666818 +15.4000 1 -22022.756 37.437752 3.3479629 10.098410 -4.9053664 0.0000000 11.335528 38.661344 54.866481 97.109761 197.78967 1.2658370 +15.6000 2 -21964.418 30.282013 10.612140 9.1697197 -12.317873 -8.7557807 0.0000000 20.633869 32.445368 63.102609 142.50956 1.2669083 +15.8000 2 -21929.730 43.212715 36.273232 3.1202292 -22.670751 -15.315878 0.0000000 33.379113 52.760374 103.23265 224.11541 1.2679094 +16.0000 1 -21941.172 83.899086 -3.5913265 0.67229438 -8.7578107 0.0000000 14.330002 35.830730 48.351296 93.513227 356.11376 1.2639551 +16.2000 2 -21958.902 33.717331 23.279509 5.4917355 -14.601117 -10.415552 0.0000000 31.811958 58.400549 185.11819 3756.9756 1.2633547 +16.4000 1 -21970.131 121.61975 -7.8567543 8.2935047 -14.398717 0.0000000 19.028428 36.349884 40.862094 47.926761 57.672357 1.2651520 +16.6000 0 -21916.539 399.17053 -1.9371190 0.73396814 0.0000000 28.987314 59.861330 88.000638 98.922699 129.27781 234.39086 1.2648592 +16.8000 0 -21905.633 286.06580 0.49914807 9.0068254 0.0000000 24.773433 57.703859 95.648721 113.99678 172.48479 453.99454 1.2638220 +17.0000 0 -21899.207 440.35812 -0.79675192 2.0447345 0.0000000 33.212497 70.643883 110.43838 133.48860 244.34593 2694.7239 1.2669228 +17.2000 0 -21937.750 314.43866 -2.9804618 0.44586232 0.0000000 25.215156 57.299696 99.752458 129.44343 289.84654 13942.939 1.2716802 +17.4000 0 -21898.176 339.10880 -9.9572506 3.3914292 0.0000000 27.337315 59.520244 76.927453 77.043233 73.229276 67.421701 1.2730843 +17.6000 0 -21945.645 251.84575 -12.605454 7.4205742 0.0000000 20.133145 44.107496 57.775853 57.654165 52.592361 38.585483 1.2748070 +17.8000 0 -21842.227 173.27344 -1.4871436 2.0248199 0.0000000 14.939232 36.476731 67.406092 85.403542 147.28048 451.20862 1.2757717 +18.0000 1 -21882.664 125.73442 0.48341522 9.6390896 -15.051568 0.0000000 23.022400 52.493720 67.421561 117.14286 350.17945 1.2733513 +18.2000 0 -21922.383 390.76361 -4.8222237 1.8167797 0.0000000 31.452842 72.209081 139.04812 194.11814 491.11677 382396.30 1.2698752 +18.4000 0 -21881.215 296.07300 -1.5904791 1.2380290 0.0000000 25.117352 58.262778 91.678468 106.19200 152.60129 353.83241 1.2682264 +18.6000 0 -21942.736 517.00842 -2.5441213 7.0934572 0.0000000 40.422788 85.550729 122.31105 135.76717 181.72580 472.89231 1.2677265 +18.8000 0 -21924.754 323.39334 -9.3362885 8.2281713 0.0000000 26.557459 58.653232 80.633801 84.188930 88.808999 99.285072 1.2648005 +19.0000 0 -21952.416 94.098534 -6.4980593 2.4604578 0.0000000 8.4390396 22.686424 42.854359 52.045827 74.529049 126.48386 1.2632096 +19.2000 1 -21850.010 121.26833 -2.7476876 2.6133540 -14.067179 0.0000000 19.384557 40.358054 48.249730 66.146143 106.26577 1.2677873 +19.4000 0 -21887.215 269.57040 -9.6585455 9.8112221 0.0000000 22.892713 52.462827 75.748006 81.041912 90.844322 115.65317 1.2706870 +19.6000 0 -21898.961 303.04260 -8.3848133 2.3589170 0.0000000 24.923120 57.540485 94.115724 112.75227 178.48319 583.69693 1.2701950 +19.8000 0 -21842.141 253.91467 -9.2350903 8.8393745 0.0000000 21.050915 47.623576 69.483530 75.500031 90.163273 143.94087 1.2699839 +20.0000 0 -21781.025 382.79874 -7.5116596 10.258697 0.0000000 29.945837 63.871665 86.976521 90.294216 92.158478 88.771699 1.2667288 +20.2000 0 -21823.166 377.46213 -1.0574348 4.6704350 0.0000000 30.831116 69.678227 114.73205 137.63809 210.95937 540.47876 1.2637217 +20.4000 0 -21882.848 404.62689 6.6700616 8.2438335 0.0000000 33.456897 76.378958 138.51141 177.22269 326.18507 2330.3714 1.2628773 +20.6000 0 -21982.793 167.44402 -0.33887523 3.5480938 0.0000000 14.936861 37.800721 73.987677 94.151399 153.55752 376.67010 1.2631588 +20.8000 1 -22008.268 56.565289 16.005581 7.1317663 -7.4647411 0.0000000 19.246396 84.020757 139.13402 386.36283 13336.454 1.2656437 +21.0000 0 -21983.520 237.27582 -3.9269805 4.8590407 0.0000000 20.054280 46.931692 75.851075 87.597689 117.81221 201.77096 1.2639940 +21.2000 0 -21954.195 275.36139 -8.4744883 5.5377512 0.0000000 22.716712 50.898871 72.828175 79.468412 100.92217 214.99730 1.2660384 +21.4000 0 -21912.617 91.050705 -6.3950453 1.5541340 0.0000000 8.1913188 22.811303 48.472143 64.423321 123.23704 538.64127 1.2657355 +21.6000 1 -21869.406 67.160332 -4.2546301 3.8504131 -7.0704746 0.0000000 12.249281 30.605833 39.154942 60.187860 111.54422 1.2651166 +21.8000 2 -21920.359 30.502380 -1.8525507 9.7182789 -11.094403 -7.4583986 0.0000000 12.730206 17.990718 27.914975 42.379633 1.2700151 +22.0000 2 -21970.148 38.031891 2.9442554 1.3660947 -12.773485 -8.5187485 0.0000000 13.641780 19.417965 31.239187 51.069414 1.2715436 +22.2000 1 -22073.361 85.649391 -9.0302238 10.209330 -9.2924062 0.0000000 15.129000 31.481684 36.422164 45.852278 64.211194 1.2724800 +22.4000 0 -22160.160 61.306732 -12.587860 8.9553394 0.0000000 5.4976471 14.961611 26.199465 29.617072 35.326400 43.883617 1.2711729 +22.6000 3 -22088.180 26.855824 -4.1128650 3.5704567 -18.681749 -14.958394 -8.3538674 0.0000000 2.6494430 6.9588735 12.488101 1.2751724 +22.8000 3 -21968.229 28.155983 21.827765 10.146961 -23.530628 -21.390467 -14.471139 0.0000000 6.6616278 20.244143 42.306002 1.2784283 +23.0000 2 -22004.760 42.778915 11.890957 0.99314016 -17.051940 -11.153108 0.0000000 19.870570 30.591166 60.187072 147.33920 1.2824029 +23.2000 2 -21980.422 54.223064 38.414291 0.53995848 -28.894615 -18.726160 0.0000000 34.415640 53.803985 106.54447 246.77936 1.2808796 +23.4000 1 -22071.910 54.704742 14.553140 9.8087873 -7.6412707 0.0000000 17.740029 67.089595 103.93505 239.63370 1363.6760 1.2801198 +23.6000 2 -22014.184 34.508163 0.091969915 2.2886503 -11.022374 -7.2900818 0.0000000 12.889182 19.254543 34.630375 69.418331 1.2777056 +23.8000 2 -21975.338 26.991951 -4.2659926 8.2115822 -7.7477803 -5.4980395 0.0000000 11.534861 16.983379 28.371591 48.137784 1.2774911 +24.0000 3 -21930.238 22.457256 49.322662 9.6994257 -36.599329 -30.649504 -19.247287 0.0000000 9.5333433 34.213655 103.45705 1.2854080 +24.2000 2 -21947.303 34.204830 -5.8567390 7.1561422 -10.866416 -7.1705068 0.0000000 11.093148 15.366360 23.164446 34.204597 1.2857703 +24.4000 3 -21945.703 21.950333 -3.6483088 2.0576670 -19.692377 -15.233596 -7.7779503 0.0000000 1.9090049 4.5221851 7.5077322 1.2869157 +24.6000 5 -21911.918 -2.1895752 -1.1346860 1.7276325 -24.050222 -18.079857 -8.9047457 -1.3982946 -0.37328457 0.0000000 -0.70095321 1.2937405 +24.8000 5 -21903.816 -46.089890 1.1274934 2.0703361 -34.311069 -21.912868 -4.9475021 4.7867981 4.2747519 0.0000000 -8.7004759 1.2901641 +25.0000 6 -21991.930 -221.82750 -4.6295123 0.41747832 -20.182290 0.44151054 21.838264 31.181612 29.515556 21.233821 0.0000000 1.2899412 +25.2000 6 -21955.973 -52.349373 -0.53940749 2.1290653 -22.085639 -12.642526 0.61788949 8.8177730 8.7170095 5.9609284 0.0000000 1.2871704 +25.4000 5 -21970.721 26.809181 2.0983763 0.76036245 -19.151552 -17.021936 -12.618722 -6.1694926 -3.9143260 0.0000000 5.4141506 1.2868122 +25.6000 4 -21971.746 16.790085 21.510996 1.6158047 -29.161867 -23.839365 -14.827517 -3.7630394 0.0000000 7.0624110 18.854483 1.2842033 +25.8000 2 -22054.250 42.079575 -7.0899477 2.1100087 -13.547908 -8.4668156 0.0000000 9.1683364 11.548589 14.864402 18.470570 1.2849885 +26.0000 4 -22025.750 12.980629 -8.8508110 0.65101910 -21.640280 -16.191964 -7.7344228 -0.83262498 0.0000000 -0.061592316 -1.6297134 1.2868738 +26.2000 5 -22050.883 20.035442 -4.1302328 1.2700150 -22.581944 -18.733358 -11.896863 -4.3995545 -2.5367820 0.0000000 3.1251180 1.2859616 +26.4000 3 -21980.422 22.756008 -9.0697927 0.91744471 -21.291531 -15.913012 -7.3873968 0.0000000 1.1651837 1.9733049 2.2388923 1.2840955 +26.6000 5 -21922.523 -3.0002899 -0.45855087 0.90218544 -26.060479 -19.564593 -9.4782952 -1.3130615 -0.27105144 0.0000000 -0.82207577 1.2841774 +26.8000 5 -21896.914 -13.577385 -1.2433985 0.95915192 -26.101579 -18.522369 -7.3861323 0.52420571 1.0423334 0.0000000 -3.0208327 1.2863953 +27.0000 5 -21948.223 -13.130409 2.1210780 0.72662920 -26.338607 -18.907522 -8.1766960 -0.23544608 0.52957819 0.0000000 -2.6024112 1.2826726 +27.2000 6 -21901.156 -179.88907 18.799809 0.43538356 -25.772615 -7.7707327 12.349770 22.420147 21.576444 15.575780 0.0000000 1.2819096 +27.4000 6 -21866.537 -119.98997 29.323364 1.2682849 -30.608542 -16.128970 1.8783859 12.510522 12.574069 9.1698116 0.0000000 1.2777898 +27.6000 6 -21879.221 -228.67264 -2.4726765 1.4256284 -21.868556 -0.56899784 21.854255 31.896968 30.254517 21.757716 0.0000000 1.2713252 +27.8000 6 -21840.391 -323.42169 0.097976983 0.29842088 -23.117520 4.1812436 31.021597 42.162298 39.832117 28.894685 0.0000000 1.2715735 +28.0000 6 -21879.283 -183.38235 -8.4278240 1.3841553 -18.136085 0.50030843 21.679112 30.727132 28.640730 19.733639 0.0000000 1.2707170 +28.2000 6 -21869.662 -237.14871 12.649422 1.9203444 -25.456854 -2.6544272 21.860673 32.590824 30.686086 21.662252 0.0000000 1.2678057 +28.4000 6 -21864.318 -161.54501 0.93778920 1.2243452 -21.743325 -4.5357336 15.520979 25.022470 23.619447 16.455690 0.0000000 1.2727444 +28.6000 6 -21862.660 -242.40977 -0.71668619 0.45941439 -19.820906 4.3865377 33.029538 44.091918 40.402942 26.878538 0.0000000 1.2704298 +28.8000 6 -21842.475 -141.00208 -7.0583477 1.1177619 -20.117806 -3.5796856 17.524382 27.281120 25.254257 16.748680 0.0000000 1.2674015 +29.0000 6 -21907.070 -70.768639 2.1493533 1.0706211 -21.909708 -11.101045 3.9501987 12.568604 12.018928 8.0091090 0.0000000 1.2684721 +29.2000 6 -21811.736 -254.78761 2.7676327 0.65893805 -20.619188 4.6651669 35.188830 46.973115 42.877834 28.246876 0.0000000 1.2643523 +29.4000 6 -21736.225 -275.93793 -0.31715554 4.0485330 -23.701905 3.1312596 34.277078 46.870708 43.283377 29.263977 0.0000000 1.2621932 +29.6000 6 -21748.096 -282.71176 7.7740283 1.5452199 -23.366780 3.1497480 32.637475 44.435360 41.250759 28.354359 0.0000000 1.2612340 +29.8000 6 -21719.930 -207.39267 9.4271326 11.504879 -33.444795 -10.877530 17.054329 31.147910 29.482047 20.241060 0.0000000 1.2651048 +30.0000 6 -21698.244 -193.29811 -0.88596678 1.2607553 -18.918530 1.2608427 25.620680 35.521388 32.661938 21.729070 0.0000000 1.2660446 +30.2000 6 -21724.496 -95.850410 -4.4007006 0.90369213 -20.068054 -7.4620270 8.9751823 17.553674 16.572986 11.194044 0.0000000 1.2666022 +30.4000 6 -21738.492 -84.597839 10.013186 0.92980188 -25.684640 -13.968526 1.2890993 10.646292 10.731486 7.7782210 0.0000000 1.2638485 +30.6000 6 -21785.789 -140.17014 -7.5577784 1.4742308 -18.593114 -2.3877638 18.347007 27.680158 25.513840 16.814783 0.0000000 1.2607187 +30.8000 6 -21834.516 -127.98286 -9.2225838 1.7612627 -19.570677 -4.2038247 15.664789 25.122416 23.315315 15.477655 0.0000000 1.2608640 +31.0000 6 -21823.766 -147.83942 -7.8253956 0.46956754 -19.074027 -2.3625019 18.139905 27.400207 25.459739 17.142873 0.0000000 1.2588223 +31.2000 6 -21796.324 -156.92604 15.435854 0.65156937 -25.765656 -8.1348394 13.835291 24.553118 23.021706 15.549465 0.0000000 1.2606235 +31.4000 6 -21791.762 -281.36346 -5.4582405 4.2843809 -21.008023 5.9601303 36.455508 48.125501 44.354925 30.059721 0.0000000 1.2604482 +31.6000 6 -21763.939 -170.08496 9.4534149 1.5046027 -24.327749 -5.2797708 18.507068 29.344901 27.180498 18.048877 0.0000000 1.2563555 +31.8000 6 -21778.129 -308.66556 17.427559 1.3269507 -28.638871 0.37551862 32.144027 45.273887 42.241724 29.321565 0.0000000 1.2558980 +32.0000 6 -21829.773 -307.63812 -6.5389838 0.85333836 -17.114456 10.069655 38.148491 48.065388 44.446468 30.846746 0.0000000 1.2536935 +32.2000 6 -21890.848 -284.21561 -9.8153896 0.62947351 -17.272652 8.3428123 35.375026 45.368242 41.987947 29.078106 0.0000000 1.2549570 +32.4000 6 -21923.727 -338.95346 4.8864670 5.3441882 -26.611487 1.7864181 29.629033 41.588475 39.469899 28.851574 0.0000000 1.2518436 +32.6000 6 -21892.947 -10.777611 5.2323856 3.3250070 -24.411722 -18.680202 -9.7408486 -2.0246697 -0.78303908 0.058513623 0.0000000 1.2539750 +32.8000 1 -21948.326 54.732605 -10.230536 3.9378688 -5.0985801 0.0000000 8.7937064 20.043743 24.142331 32.515295 48.670704 1.2512006 +33.0000 3 -21965.527 25.630867 -4.0960007 0.36879659 -13.437685 -11.529409 -6.7698211 0.0000000 2.2364146 6.1136633 11.959780 1.2492782 +33.2000 4 -21917.389 26.431412 4.8216147 1.2418392 -18.130708 -15.643115 -10.753189 -3.0305172 0.0000000 5.6396125 14.190359 1.2460067 +33.4000 3 -21926.949 22.348667 8.3844509 1.6522374 -21.480965 -17.209639 -9.6878311 0.0000000 3.4057354 9.9034453 21.744611 1.2432523 +33.6000 4 -21902.195 25.307117 13.418394 0.75033420 -20.384523 -17.770575 -12.451340 -3.6332780 0.0000000 6.9725224 17.450846 1.2430351 +33.8000 3 -21972.836 26.274940 24.555012 4.0713992 -24.187345 -20.759857 -13.415327 0.0000000 6.1237106 19.079750 41.876771 1.2465385 +34.0000 2 -21982.844 45.938271 19.294521 1.5109925 -19.758614 -13.067935 0.0000000 24.440489 37.338550 69.231779 140.12200 1.2434710 +34.2000 1 -21906.520 76.087723 -4.9844341 2.3361132 -7.6091794 0.0000000 13.810518 37.679275 53.381547 119.47818 782.76332 1.2400380 +34.4000 1 -21975.092 51.608849 15.298812 9.7687778 -7.4299464 0.0000000 17.094333 63.526616 98.855557 253.63995 5616.6401 1.2384131 +34.6000 0 -22020.732 179.43867 2.1443193 1.7568851 0.0000000 16.420360 41.617634 76.352364 94.467682 152.51094 455.97469 1.2426656 +34.8000 0 -22035.283 143.42967 6.5446954 9.0433025 0.0000000 14.717748 41.343536 100.05069 141.07860 284.59210 1211.3068 1.2457119 +35.0000 0 -22047.230 184.71848 2.5366127 0.87365943 0.0000000 16.799595 42.562670 80.870120 103.61767 184.17797 637.70364 1.2452488 +35.2000 1 -22017.516 73.841324 12.259260 5.0421333 -9.1687516 0.0000000 18.882702 64.136841 97.864168 238.83909 2557.0603 1.2453630 +35.4000 1 -21930.225 136.99763 -4.4941883 3.2075496 -15.218131 0.0000000 22.197732 47.701874 61.973795 129.36057 1040.7398 1.2470968 +35.6000 0 -21967.328 196.79926 -3.0462577 1.9394989 0.0000000 17.475335 43.346147 75.644481 93.457489 163.95176 783.75203 1.2434295 +35.8000 0 -21966.182 154.90388 5.6997590 1.5887905 0.0000000 14.911934 40.845385 97.271339 142.33555 346.27958 2743.9388 1.2430283 +36.0000 0 -21959.393 159.16824 -7.9973550 6.1725030 0.0000000 13.908079 34.067906 56.714608 67.047711 101.70066 284.33230 1.2453640 +36.2000 0 -21944.074 186.85310 3.7274730 5.4782081 0.0000000 17.775797 46.037389 88.359357 111.58023 181.78267 429.47086 1.2450074 +36.4000 0 -21959.447 332.32477 2.3553174 8.7971430 0.0000000 28.117825 65.529440 115.03292 143.64899 249.40186 948.59370 1.2442194 +36.6000 0 -21932.764 210.02179 -3.1781089 10.238000 0.0000000 19.010881 49.014464 106.58392 149.94551 352.24567 4577.7409 1.2422059 +36.8000 0 -21949.551 232.75848 -6.9544568 6.8374071 0.0000000 19.154809 43.313975 63.944686 69.364582 79.242806 98.430144 1.2389812 +37.0000 1 -21873.670 86.431168 -8.8416109 2.6452084 -8.9829345 0.0000000 13.087489 25.077781 27.994651 32.524094 39.597184 1.2409797 +37.2000 2 -21780.715 58.004936 25.897877 1.2339296 -28.410478 -17.939633 0.0000000 32.615704 56.499067 162.33701 1273.1947 1.2404621 +37.4000 1 -21883.699 71.819046 -2.9764950 2.7484930 -7.4612471 0.0000000 13.328147 34.075599 44.803041 74.891014 162.74030 1.2404244 +37.6000 1 -21817.223 52.321541 17.640228 9.5224676 -7.4711436 0.0000000 19.070307 83.229432 138.63967 389.73177 9232.9453 1.2378094 +37.8000 1 -21788.057 68.093147 -6.6010375 1.4969988 -6.6976833 0.0000000 11.200191 24.816067 29.710422 39.883005 59.618685 1.2381405 +38.0000 4 -21711.166 19.642609 -5.4505825 0.58035171 -16.973101 -13.527845 -7.7237737 -1.5522756 0.0000000 2.1665386 4.6687115 1.2363611 +38.2000 5 -21741.273 25.233891 -4.3743129 3.0848842 -21.376779 -18.505924 -13.050369 -5.7509905 -3.4712360 0.0000000 3.8772371 1.2377914 +38.4000 4 -21776.324 31.747383 -1.5676244 0.99075073 -15.280862 -13.784158 -10.040464 -2.9197634 0.0000000 5.2723091 12.305336 1.2399076 +38.6000 3 -21827.861 26.588558 0.19344282 2.0099399 -17.749164 -14.552344 -8.4979571 0.0000000 2.9775721 8.1439835 15.147582 1.2385107 +38.8000 5 -21797.912 -25.966537 8.9523163 0.62613797 -31.036716 -21.208309 -8.0805509 0.63929744 1.2064354 0.0000000 -3.7947494 1.2346338 +39.0000 5 -21751.449 6.9065323 -8.0824995 1.7737796 -22.053641 -16.861469 -8.7212907 -1.7092775 -0.62409054 0.0000000 -0.32508144 1.2367685 +39.2000 6 -21760.359 40.627670 -1.1572711 2.0582650 -23.905912 -21.886408 -17.366900 -10.814751 -8.6176192 -4.9507250 0.0000000 1.2412306 +39.4000 4 -21861.344 13.325531 -5.6467929 1.1072866 -21.449559 -16.222857 -8.0891138 -1.1305105 0.0000000 0.84052769 1.0270638 1.2413235 +39.6000 5 -21848.186 -4.6334381 6.0659680 1.7053111 -25.572703 -19.492426 -9.8342674 -1.9219966 -0.78336299 0.0000000 0.73539039 1.2461290 +39.8000 4 -21959.375 30.044300 2.8111556 0.90607810 -13.980786 -13.250555 -10.119836 -3.0951354 0.0000000 5.9537516 14.744648 1.2454659 +40.0000 5 -21932.102 -54.188408 -8.0646057 1.5549638 -34.699365 -19.298757 -1.7129295 6.8426782 5.8486886 0.0000000 -14.179151 1.2439584 diff --git a/ensemble_md/tests/data/dhdl/forced-swap/dhdl_1.xvg b/ensemble_md/tests/data/dhdl/forced-swap/dhdl_1.xvg new file mode 100644 index 0000000..18bfd21 --- /dev/null +++ b/ensemble_md/tests/data/dhdl/forced-swap/dhdl_1.xvg @@ -0,0 +1,238 @@ +# This file was created Sun Jan 19 05:14:48 2025 +# Created by: +# :-) GROMACS - gmx mdrun, 2022.5-dev (-: +# +# Executable: /projects/anfr8476/pkgs/gromacs-2022.5-wl/bin/gmx +# Data prefix: /projects/anfr8476/pkgs/gromacs-2022.5-wl +# Working dir: /gpfs/alpine1/scratch/anfr8476/EEXE/test_forced_swap/small_mol/forced_random/solv/rep1/sim_1/iteration_0 +# Command line: +# gmx mdrun -s sys_EE.tpr -ntomp 6 -ntmpi 1 +# gmx mdrun is part of G R O M A C S: +# +# Great Red Owns Many ACres of Sand +# +@ title "dH/d\xl\f{} and \xD\f{}H" +@ xaxis label "Time (ps)" +@ yaxis label "dH/d\xl\f{} and \xD\f{}H (kJ/mol [\xl\f{}]\S-1\N)" +@TYPE xy +@ subtitle "T = 300 (K) " +@ view 0.15, 0.15, 0.75, 0.85 +@ legend on +@ legend box on +@ legend loctype view +@ legend 0.78, 0.8 +@ legend length 2 +@ s0 legend "Thermodynamic state" +@ s1 legend "Total Energy (kJ/mol)" +@ s2 legend "dH/d\xl\f{} coul-lambda = 0.0000" +@ s3 legend "dH/d\xl\f{} vdw-lambda = 0.0000" +@ s4 legend "dH/d\xl\f{} bonded-lambda = 0.0000" +@ s5 legend "\xD\f{}H \xl\f{} to (0.0000, 0.0000, 0.0000)" +@ s6 legend "\xD\f{}H \xl\f{} to (0.1000, 0.1000, 0.1000)" +@ s7 legend "\xD\f{}H \xl\f{} to (0.3000, 0.3000, 0.3000)" +@ s8 legend "\xD\f{}H \xl\f{} to (0.6000, 0.6000, 0.6000)" +@ s9 legend "\xD\f{}H \xl\f{} to (0.7000, 0.7000, 0.7000)" +@ s10 legend "\xD\f{}H \xl\f{} to (0.8500, 0.8500, 0.8500)" +@ s11 legend "\xD\f{}H \xl\f{} to (1.0000, 1.0000, 1.0000)" +@ s12 legend "pV (kJ/mol)" +0.0000 0 -22063.117 380.37497 0.24513382 0.20445776 0.0000000 28.964554 59.920118 89.915347 106.49931 172.05255 648.41902 1.2456253 +0.2000 0 -22123.498 185.25526 -6.7176776 -0.16935317 0.0000000 15.301680 35.351391 56.037051 67.335149 110.45522 325.98298 1.2436013 +0.4000 0 -22072.070 247.86139 -8.6273279 2.2429981 0.0000000 19.066623 39.711855 49.442811 49.263879 46.928814 42.509227 1.2444942 +0.6000 0 -22036.730 410.21466 -8.3666840 2.4541743 0.0000000 30.667115 62.099183 81.990070 88.707933 115.69248 265.07671 1.2498491 +0.8000 0 -22084.967 98.235893 -1.9157153 2.1178110 0.0000000 8.9265637 22.689910 44.185702 60.146873 136.20498 1143.0783 1.2471339 +1.0000 2 -21954.889 24.003851 25.676590 3.4557798 -16.508252 -10.599991 0.0000000 22.960929 39.871886 98.302744 341.76277 1.2460160 +1.2000 1 -21986.957 35.640335 11.113575 7.7264471 -5.0797808 0.0000000 12.207289 45.782205 70.304117 148.84934 423.69797 1.2457204 +1.4000 1 -21940.055 36.253139 6.7384052 8.4299231 -5.3290187 0.0000000 10.235611 34.933316 53.984210 129.48717 753.84222 1.2415191 +1.6000 2 -21956.441 -0.095548630 20.830166 -0.080615357 -2.0498629 -2.0951328 0.0000000 16.075551 30.688392 80.842703 270.04834 1.2400542 +1.8000 2 -21987.457 -0.46980667 -0.78758383 7.1828871 -0.60363535 -0.62221625 0.0000000 4.5333286 8.5298234 20.947020 55.159826 1.2372786 +2.0000 1 -21992.781 6.4405842 14.154472 9.0437889 -2.5493999 0.0000000 8.3767805 43.542128 73.997389 198.70023 1802.3988 1.2395592 +2.2000 1 -21967.520 41.050461 11.084563 5.2500954 -5.3585716 0.0000000 13.044504 54.280245 89.637328 233.39742 1556.2908 1.2355899 +2.4000 1 -21964.355 78.131073 10.280168 7.4725647 -10.409492 0.0000000 17.325478 50.937616 75.705845 170.92429 749.42883 1.2345564 +2.6000 0 -21995.420 397.60333 0.22863549 3.4565067 0.0000000 32.299328 70.635140 106.33589 125.53289 213.50665 1232.5392 1.2303432 +2.8000 0 -21980.719 179.38831 0.20659888 1.6527075 0.0000000 15.554199 37.186337 68.393514 89.839096 177.77979 791.01785 1.2305677 +3.0000 0 -21993.803 182.97409 0.69562757 5.4932413 0.0000000 16.389230 39.518492 71.698702 92.840069 179.43478 874.62342 1.2329835 +3.2000 0 -22003.453 144.15831 -0.96879393 5.8161182 0.0000000 13.902746 40.329451 118.76405 194.20257 602.15507 105934.29 1.2326363 +3.4000 0 -22042.418 105.97189 4.5090079 3.3981245 0.0000000 10.485345 29.894345 85.383427 136.88870 400.12315 17316.299 1.2326970 +3.6000 1 -22062.328 -7.0529118 7.6204619 0.22319555 1.1111673 0.0000000 3.4138664 27.607557 49.939168 137.69347 796.72850 1.2279760 +3.8000 2 -22017.875 15.597519 2.8978992 6.2560425 -8.6545773 -5.5938435 0.0000000 7.1103497 10.522270 20.217997 46.256661 1.2291079 +4.0000 1 -22085.812 69.638588 -2.1199682 0.020382538 -7.5974136 0.0000000 10.774484 22.206436 28.477806 52.628858 170.83455 1.2303652 +4.2000 2 -22009.875 13.657463 11.387631 3.2248287 -8.5501683 -5.6055719 0.0000000 11.230701 18.322983 38.851193 95.050993 1.2275279 +4.4000 1 -22096.500 80.056831 -12.059097 8.2505589 -8.8811432 0.0000000 10.999766 14.426365 12.696912 7.8788030 1.1243497 1.2273031 +4.6000 0 -22104.812 77.140358 -9.7077398 7.5069141 0.0000000 6.6601351 16.057365 27.357976 35.328538 73.342308 375.82681 1.2291389 +4.8000 1 -22156.383 63.298523 8.7745390 9.7555971 -8.7437561 0.0000000 15.707103 53.848024 84.253121 199.03232 841.81276 1.2358016 +5.0000 0 -22229.758 157.60736 -4.6314988 8.6364546 0.0000000 13.454796 30.547428 47.744788 55.301234 77.147670 146.33828 1.2355039 +5.2000 0 -22199.309 210.18065 -9.3073463 8.5177402 0.0000000 17.104805 36.688895 46.059932 46.071996 46.309774 64.135043 1.2338841 +5.4000 0 -22251.871 181.73822 0.053642809 3.5217218 0.0000000 16.220961 39.185994 69.077986 88.362057 173.09122 1074.9301 1.2358751 +5.6000 0 -22232.531 322.80783 -3.0520132 3.0393968 0.0000000 25.550430 55.086555 83.361124 99.247783 174.70249 1219.7818 1.2339997 +5.8000 0 -22321.662 220.76495 6.1883707 7.0033112 0.0000000 19.559707 48.206100 110.24353 162.62434 403.40492 8716.0384 1.2346649 +6.0000 0 -22252.781 79.429680 -8.4059563 1.6952215 0.0000000 6.8587939 20.250725 63.373316 106.23323 334.29055 7102.4341 1.2343625 +6.2000 1 -22216.020 66.812027 16.320114 2.5852201 -9.2050521 0.0000000 16.895595 63.470765 102.33020 253.38216 1399.9260 1.2308182 +6.4000 0 -22249.635 298.45361 3.3439150 7.9503660 0.0000000 25.014282 56.648792 102.36870 134.61367 267.39838 1474.8717 1.2323335 +6.6000 0 -22212.629 131.47971 -0.70032507 2.6052177 0.0000000 11.942012 30.859170 67.130418 94.303283 197.43351 746.68818 1.2320479 +6.8000 0 -22172.598 279.55814 -8.3881102 -0.46682590 0.0000000 20.917342 47.726507 104.03963 154.52351 413.88615 45250.006 1.2322609 +7.0000 0 -22181.936 189.63036 -6.1016631 1.5779374 0.0000000 16.799956 44.966903 108.34963 162.38308 431.63006 111573.44 1.2344795 +7.2000 0 -22262.195 143.31857 -0.16188276 0.93329501 0.0000000 13.679171 40.224860 113.61802 176.52375 441.41704 3244.5552 1.2375416 +7.4000 0 -22237.852 211.26128 9.7590227 8.8666286 0.0000000 19.458367 47.867000 102.03138 144.49013 335.22144 3442.9529 1.2348285 +7.6000 0 -22085.666 327.41754 -8.8821821 3.1098647 0.0000000 25.832738 58.907194 111.06839 149.34052 309.43748 2349.2128 1.2386909 +7.8000 0 -22109.910 110.73479 -7.8508215 1.0928804 0.0000000 9.0502902 20.633523 27.266903 27.977394 29.472811 35.266761 1.2399223 +8.0000 1 -22055.938 3.6515026 -8.4732475 -1.2897273 1.8952464 0.0000000 -0.31770867 0.39499644 1.5811729 6.2196028 20.464847 1.2383769 +8.2000 3 -22039.273 -6.1153107 2.6650901 0.13883179 -1.1320734 -0.88626684 0.16995003 0.0000000 -0.32545865 -0.32439987 2.1090806 1.2417935 +8.4000 2 -22029.586 8.0214005 1.5985916 0.51018029 -3.5751468 -2.2033171 0.0000000 3.8281575 6.1832703 12.381533 25.008114 1.2414387 +8.6000 3 -21974.238 -6.1143360 -5.5539575 0.47096589 -1.8650108 -0.20313836 1.4211599 0.0000000 -1.2779387 -3.5679273 -5.6488057 1.2424345 +8.8000 5 -22034.162 -8.2475653 23.101847 0.076807261 0.23358418 0.47227380 0.37728918 -0.74363710 -0.92760160 0.0000000 5.6074036 1.2442961 +9.0000 4 -22044.168 3.2701912 -4.5842767 0.86597192 8.7815499 6.5288160 3.1707452 0.27486054 0.0000000 0.60503664 3.1937708 1.2435251 +9.2000 5 -22034.758 -9.9755363 -4.1803389 1.7121530 5.1858292 5.5399470 5.3378355 3.0451970 1.8857936 0.0000000 -1.6195716 1.2449493 +9.4000 4 -21986.361 6.3532333 -2.1719949 8.1900616 3.5334752 1.4550353 -0.73854570 -0.90881143 0.0000000 2.8666307 9.1806740 1.2447572 +9.6000 3 -21944.855 -2.9929848 -0.17232573 5.5886669 -1.5634925 -1.1038417 -0.48792492 0.0000000 0.35611611 1.7036686 5.3953754 1.2484543 +9.8000 5 -21955.770 -49.862103 7.4975524 -1.5922364 -1.3215348 3.6724130 9.3049048 8.2278455 5.6491845 0.0000000 -7.2651188 1.2491267 +10.0000 5 -21967.336 -2.9581909 -2.0696764 -0.61334145 8.0698944 7.0343581 5.0096473 2.0027297 1.0928458 0.0000000 -0.44904307 1.2488116 +10.2000 6 -22019.838 -373.87994 2.3451509 -1.3687025 9.6117721 34.513958 55.106587 56.378997 50.727760 34.731672 0.0000000 1.2501415 +10.4000 6 -22029.926 -207.39174 16.539103 -0.25108862 5.8814119 20.940487 35.360270 36.094722 31.888980 20.661252 0.0000000 1.2482717 +10.6000 6 -22068.697 -170.60753 -7.3912816 0.65006489 11.587498 24.205113 37.104381 36.884163 32.255265 20.354056 0.0000000 1.2502905 +10.8000 6 -22028.877 -140.97063 -2.7065475 4.5314469 6.3732107 17.516451 30.223049 31.300408 27.298938 16.870837 0.0000000 1.2499219 +11.0000 6 -22113.031 -220.76056 1.9201188 2.7532279 6.4295740 22.510632 37.638514 38.695958 34.409074 22.644845 0.0000000 1.2464842 +11.2000 6 -22155.301 -218.05275 -5.9230161 -0.033734441 12.111800 28.125497 44.062659 44.281037 38.945760 24.927054 0.0000000 1.2468830 +11.4000 6 -22182.430 -131.42792 -0.53263575 1.9387648 8.4870334 18.642855 29.948994 30.017923 25.988787 15.902415 0.0000000 1.2473830 +11.6000 6 -22231.621 -418.17108 0.27503580 5.0786781 4.8329306 35.399962 63.888607 68.133213 61.385768 41.421127 0.0000000 1.2473550 +11.8000 6 -22208.625 -289.30295 -3.2606311 8.6513357 1.7964301 23.907420 46.090472 50.071183 44.898183 29.734043 0.0000000 1.2513050 +12.0000 6 -22250.426 -87.247154 13.540112 0.31441733 5.0837761 11.599219 18.713004 18.316488 15.655646 9.3371081 0.0000000 1.2530589 +12.2000 5 -22241.441 -37.400944 27.919945 6.4175210 -11.446920 -6.8661533 -1.1173608 1.1476795 0.77357969 0.0000000 0.91469472 1.2524722 +12.4000 4 -22315.949 -12.477786 0.79243642 1.2321866 -1.3861126 0.11620879 1.8920271 0.97289636 0.0000000 -1.4638993 -1.2983478 1.2519168 +12.6000 4 -22306.520 -12.784578 -0.57131922 2.7722757 -2.6259809 -0.70704807 1.4285052 0.92562584 0.0000000 -1.7662607 -3.4708206 1.2512546 +12.8000 1 -22350.160 31.565369 -0.25344473 6.1402893 -3.9986330 0.0000000 7.1229355 24.661038 39.903199 108.94175 825.95445 1.2528683 +13.0000 2 -22337.949 -1.4803371 64.495872 8.1166821 -9.3640905 -8.3854418 0.0000000 53.306006 106.71687 343.50213 3664.6861 1.2511231 +13.2000 1 -22251.654 29.179090 17.594234 7.0482106 -5.1104847 0.0000000 13.050239 61.077936 102.73563 260.28766 1128.8502 1.2512796 +13.4000 0 -22299.518 63.682655 0.62696403 4.7927632 0.0000000 6.5804071 18.909405 48.091201 70.846341 157.86129 653.68992 1.2484303 +13.6000 1 -22282.484 34.273903 9.9591436 7.8635139 -5.2306294 0.0000000 11.015366 40.189722 62.103782 138.31470 480.57773 1.2539706 +13.8000 1 -22322.496 37.217628 17.351440 4.5971513 -5.8040009 0.0000000 13.264155 53.662897 86.050828 211.94249 1532.8136 1.2570487 +14.0000 1 -22329.844 -0.54661179 22.175713 2.9906878 -1.4613918 0.0000000 10.020320 68.891312 124.68167 350.27282 2373.1222 1.2572479 +14.2000 1 -22282.922 11.884523 9.4440632 7.7030196 -2.0779410 0.0000000 9.6237489 57.322835 101.49946 279.27572 1541.1598 1.2547665 +14.4000 2 -22338.566 7.6919918 7.5708694 5.8520370 -5.1461208 -3.5748677 0.0000000 12.816030 25.854584 88.345223 706.58458 1.2562047 +14.6000 2 -22320.611 0.12564850 -7.6386147 7.2267737 0.94724164 0.42846543 0.0000000 1.0704109 2.2220010 5.3579649 11.396839 1.2606012 +14.8000 4 -22308.605 -3.3524189 11.672612 -0.45349586 5.7922684 4.2592696 1.7445395 -0.32068274 0.0000000 2.9388807 15.325177 1.2598598 +15.0000 3 -22295.977 -5.3864174 -4.3283467 0.40267175 3.7092334 3.0712293 2.2589336 0.0000000 -0.91945441 -1.8890516 -0.94619980 1.2581377 +15.2000 5 -22247.254 -48.280014 9.1981411 0.66326958 -5.4503479 0.24706002 6.6306358 6.7792054 4.7604306 0.0000000 -6.7265350 1.2549877 +15.4000 5 -22247.869 1.0473652 6.8587799 0.19580635 6.3129776 4.8814313 2.5281690 -0.015110120 -0.38729595 0.0000000 2.6533902 1.2549075 +15.6000 3 -22216.332 -4.1162109 7.9813714 0.27978957 0.24719042 0.10308405 -0.13969186 0.0000000 0.68323855 3.3827613 10.998040 1.2551044 +15.8000 2 -22256.297 37.644093 -4.1189189 -0.037831888 -19.959541 -10.821552 0.0000000 2.6899924 0.81254086 -3.8367400 -8.1774723 1.2534037 +16.0000 0 -22310.334 141.24101 -2.5419540 0.074759156 0.0000000 11.913966 28.893480 59.789259 86.889112 237.66882 9516.0531 1.2577304 +16.2000 0 -22339.025 63.985813 1.3844458 6.2057953 0.0000000 6.4694643 18.710611 55.296305 85.433482 200.48965 980.92036 1.2534040 +16.4000 1 -22274.004 60.392372 5.6304946 1.2071807 -7.4849365 0.0000000 11.904154 37.744644 59.958385 158.85209 958.63337 1.2524360 +16.6000 1 -22256.723 54.927048 3.1325564 -0.34637871 -5.7936826 0.0000000 12.202207 50.817514 88.568952 291.57305 29354.308 1.2533095 +16.8000 1 -22249.430 55.625744 12.196953 3.4015484 -7.4364019 0.0000000 14.359313 54.454429 90.550963 266.10838 3668.5201 1.2524600 +17.0000 0 -22285.439 448.06897 -2.5766921 8.8970003 0.0000000 33.578743 68.814178 100.49199 114.93164 158.87210 299.14316 1.2481967 +17.2000 0 -22341.184 192.53743 -3.2619152 2.3435504 0.0000000 16.295143 37.672931 61.567366 76.187727 140.11648 663.63798 1.2451923 +17.4000 0 -22322.148 430.95560 -12.257842 8.6959343 0.0000000 31.167752 60.017055 67.824525 63.580761 49.300379 16.612206 1.2458956 +17.6000 0 -22301.584 208.91492 -6.8529496 0.085796148 0.0000000 16.485051 35.900766 52.090172 58.867939 80.766431 164.42023 1.2461833 +17.8000 0 -22272.029 331.44000 -11.647017 8.1456738 0.0000000 25.655105 56.266355 97.209376 127.95347 295.39243 14973.484 1.2462865 +18.0000 0 -22212.570 273.42548 -3.9349127 9.0648108 0.0000000 21.620747 46.133100 69.665747 81.797482 129.91056 469.89758 1.2466862 +18.2000 0 -22287.883 285.37918 -10.307729 2.2347739 0.0000000 22.486915 47.298801 58.207592 58.621192 63.553115 114.06345 1.2481267 +18.4000 0 -22145.988 333.62146 -6.3052740 9.2008133 0.0000000 26.325515 54.764805 69.182400 69.515071 67.459887 63.811563 1.2474544 +18.6000 0 -22186.383 267.80838 -0.044875801 3.7951536 0.0000000 21.504021 50.658061 115.02972 169.78397 392.09584 1636.8186 1.2477745 +18.8000 0 -22205.482 161.93576 -0.34548044 0.14515476 0.0000000 13.872905 33.145865 59.612983 75.011326 121.60432 256.97645 1.2513584 +19.0000 0 -22218.840 83.653542 3.3815000 2.4392703 0.0000000 8.4301898 24.738115 70.451878 108.61458 255.72461 1161.4162 1.2490025 +19.2000 1 -22225.816 28.992832 6.7843909 6.8614302 -4.2702452 0.0000000 8.8021939 30.270751 46.062802 102.65584 412.05091 1.2530230 +19.4000 1 -22267.793 34.392212 8.8414307 8.6368151 -5.3356225 0.0000000 10.642013 39.137529 61.870160 149.71177 801.37708 1.2520683 +19.6000 1 -22212.652 50.974731 -5.8450480 8.3360672 -6.0634778 0.0000000 8.5569197 17.428295 21.116938 30.982165 56.495486 1.2522227 +19.8000 1 -22223.717 86.363945 -6.6460075 4.2686701 -9.9130572 0.0000000 12.189976 18.580675 19.204577 21.889573 37.852264 1.2555954 +20.0000 0 -22375.551 146.77594 -5.5246077 0.59464180 0.0000000 12.261497 29.428313 56.592217 78.742014 192.50787 2819.5712 1.2583466 +20.2000 1 -22347.076 30.860828 -1.5329188 0.43941161 -3.2269539 0.0000000 5.5536707 20.026346 33.550656 96.254117 697.40272 1.2541245 +20.4000 2 -22282.061 -5.4182854 25.242186 5.8948073 -0.58753003 -2.0287716 0.0000000 18.951629 34.386920 80.362746 210.23101 1.2543843 +20.6000 1 -22315.828 6.6445999 -3.5109258 6.4673595 -0.54266735 0.0000000 4.0795611 30.591630 59.384203 220.84566 15345.264 1.2581426 +20.8000 2 -22250.193 1.2998734 16.935099 0.13051245 -1.5749974 -1.9442733 0.0000000 12.888325 23.820951 58.762973 171.84150 1.2546188 +21.0000 2 -22186.564 8.7881432 0.37205184 8.9063215 -5.5532287 -3.6082333 0.0000000 6.7449983 10.456288 19.633309 38.411672 1.2537760 +21.2000 2 -22205.883 0.26688194 11.416101 0.40980434 -0.71761501 -0.99785288 0.0000000 10.302622 19.876719 52.923018 183.05859 1.2511090 +21.4000 2 -22152.240 6.5085907 58.636467 -0.81475329 -11.906884 -9.0756700 0.0000000 41.701483 78.768083 212.75425 818.24864 1.2526201 +21.6000 1 -22187.084 7.3956718 10.391785 8.4716206 -2.2487646 0.0000000 7.5945218 42.132508 73.817188 211.41929 2454.5461 1.2486491 +21.8000 2 -22194.258 -0.38702011 77.588310 1.2274858 -10.731014 -9.4075597 0.0000000 57.925793 113.88546 333.96356 1481.8194 1.2487128 +22.0000 1 -22190.514 63.833469 6.5712667 5.8827133 -8.2305720 0.0000000 13.851624 40.034435 58.349491 124.80172 494.37484 1.2488669 +22.2000 0 -22238.193 5.4710140 2.6938276 6.7787938 0.0000000 2.6463186 15.780425 85.316239 151.91984 444.19500 6702.7125 1.2461667 +22.4000 1 -22300.453 46.779732 10.482294 0.59831297 -5.5554927 0.0000000 13.307013 59.877559 101.54484 267.21489 1374.9976 1.2440656 +22.6000 1 -22257.076 30.195164 2.5611176 0.63492239 -3.5087919 0.0000000 6.3558254 19.783835 29.147105 58.910685 156.20571 1.2425275 +22.8000 1 -22264.779 50.085583 -8.1943207 4.5880752 -5.2447802 0.0000000 7.1350825 11.401227 11.918630 13.377073 19.312722 1.2412682 +23.0000 1 -22173.357 7.5795593 6.3839278 1.5011026 -0.89704379 0.0000000 6.3955347 45.231982 82.244026 224.49409 944.58243 1.2437327 +23.2000 2 -22122.311 8.5476418 2.7281432 0.28343135 -3.6435800 -2.3294223 0.0000000 5.2460837 9.2497127 21.940159 57.491776 1.2404442 +23.4000 1 -22128.172 111.40518 2.4728804 3.6223645 -13.532013 0.0000000 18.349567 37.010122 45.455772 69.967320 138.80584 1.2409153 +23.6000 0 -22184.758 130.95444 -3.3703783 4.0143318 0.0000000 11.535540 27.879275 49.829751 64.496481 128.06466 708.46703 1.2399184 +23.8000 1 -22187.262 67.214905 2.9626706 2.7961268 -7.9740694 0.0000000 12.773546 34.229441 48.478078 96.596403 284.51613 1.2409074 +24.0000 0 -22195.779 420.56708 -1.1843930 6.9367981 0.0000000 30.986995 64.316148 105.61484 135.22354 279.38503 2468.9362 1.2385598 +24.2000 0 -22227.984 118.08287 -3.6478009 8.7725067 0.0000000 11.018119 28.179044 58.083047 80.283613 181.79803 1830.3540 1.2387460 +24.4000 1 -22148.146 77.507851 3.6515021 -0.21849477 -9.1862173 0.0000000 13.241065 31.299518 42.702152 85.547245 310.30421 1.2400618 +24.6000 1 -22062.449 63.530128 12.798860 -0.32547787 -7.7452170 0.0000000 15.689281 59.841118 97.965779 263.79233 2426.1604 1.2382207 +24.8000 1 -22005.170 74.251648 3.2705047 4.3812819 -9.0083448 0.0000000 14.519345 44.147858 70.051100 210.09880 7089.3308 1.2387300 +25.0000 0 -22024.516 30.369602 -9.6185284 5.0535212 0.0000000 2.4512644 6.8737707 17.418252 26.526064 64.462642 290.62088 1.2375727 +25.2000 1 -22076.844 39.185238 6.2386956 3.8366790 -5.0740450 0.0000000 10.304454 42.884387 74.095261 229.83853 3174.9801 1.2368743 +25.4000 1 -22072.762 -12.950279 7.7799001 4.1627312 0.73139891 0.0000000 2.6446546 25.850138 46.412992 115.88636 382.56899 1.2428060 +25.6000 2 -22022.617 -8.7583618 39.289188 0.43697321 -0.069896739 -1.9055863 0.0000000 27.270042 52.430475 137.71798 468.23183 1.2414815 +25.8000 2 -21995.684 11.544287 25.368168 0.88082772 -9.9460974 -6.6657976 0.0000000 19.391150 34.422784 84.251459 279.00740 1.2427126 +26.0000 2 -22013.734 -0.97153473 1.0352517 0.37217414 2.0886064 0.90981583 0.0000000 4.5148911 10.171087 31.387695 114.13771 1.2407267 +26.2000 3 -22006.170 -3.3641872 1.8024248 0.46893001 1.5645509 1.3661467 0.84603766 0.0000000 0.042127706 1.0429079 4.2534636 1.2387915 +26.4000 4 -21972.297 4.5946808 30.973831 1.1443423 3.7386640 0.54727062 -2.8174878 -2.5615631 0.0000000 9.7702062 39.381926 1.2371771 +26.6000 2 -21868.564 -3.3991776 8.9386644 0.94912362 1.8210411 0.44894344 0.0000000 9.3975678 19.662753 60.524247 291.71612 1.2382967 +26.8000 2 -21852.299 -4.8157978 0.71743762 -0.30861020 5.6167826 2.6259708 0.0000000 3.6559806 8.5428897 24.096585 64.190461 1.2372078 +27.0000 2 -21831.916 17.198898 -9.3614578 0.0031294152 -5.4671229 -2.9412694 0.0000000 0.030049150 -0.35970009 0.54226590 8.4278907 1.2335136 +27.2000 4 -21814.750 1.2765083 -6.4820757 1.6460162 7.2987528 5.7840560 3.2550229 0.50917311 0.0000000 -0.053402054 1.4151858 1.2330657 +27.4000 5 -21795.449 -16.479387 -6.0105362 -0.90803027 6.1393873 7.2648079 7.9151757 5.1036972 3.2907786 0.0000000 -3.4533533 1.2336932 +27.6000 3 -21797.379 -0.047523499 10.439412 6.2698536 -1.5213732 -2.0678562 -2.2827990 0.0000000 2.2106458 8.8831765 25.563920 1.2316054 +27.8000 2 -21749.328 9.0153027 -4.3687057 0.23042163 -0.64830756 -0.94559590 0.0000000 1.6167076 2.8941597 7.7715399 23.336713 1.2345363 +28.0000 4 -21754.523 -0.11727333 24.677389 3.1158757 -1.5791558 -2.6645001 -3.6631669 -2.0903816 0.0000000 6.5911512 23.266404 1.2344348 +28.2000 3 -21788.988 0.98942184 -1.5538008 0.51647890 4.7000468 3.3168067 1.3789131 0.0000000 0.25619283 2.1383696 7.6245275 1.2337235 +28.4000 2 -21825.998 -1.3777046 1.8925846 -0.13955200 2.9486142 1.2708976 0.0000000 4.0246057 7.8498464 17.739700 36.296793 1.2385468 +28.6000 2 -21907.912 13.189369 -8.1056032 3.4622760 -4.4918212 -2.5688988 0.0000000 1.0433816 1.0429041 1.4973046 4.0461646 1.2380788 +28.8000 3 -21955.018 -1.6726131 -10.304109 1.6428899 4.6547377 4.0262319 2.7155210 0.0000000 -1.0422430 -2.4795571 -3.2631084 1.2377087 +29.0000 4 -21993.809 -15.094392 23.465080 -0.84041184 -7.2299570 -4.7897407 -1.8287399 -0.47694799 0.0000000 2.5653031 12.433729 1.2405692 +29.2000 2 -21967.043 32.856323 -2.4734893 6.0094852 -17.504088 -10.078834 0.0000000 6.2827597 7.2705447 10.306114 22.699953 1.2409846 +29.4000 1 -21975.965 51.662086 -5.6361928 2.1018338 -5.4287711 0.0000000 7.5456716 13.601434 15.335976 19.577335 30.452277 1.2400640 +29.6000 1 -21900.041 28.735554 -13.580088 6.6138549 -2.5178304 0.0000000 3.0156432 2.8426310 1.7037727 -0.73470696 -3.5003979 1.2391561 +29.8000 3 -21847.371 0.0074348450 13.718186 2.2167006 -1.0816229 -1.4691095 -1.8460773 0.0000000 2.1977995 9.2191591 27.072572 1.2390113 +30.0000 3 -21881.934 -6.3628616 27.363569 2.2915950 -9.9821031 -7.6188723 -4.2665972 0.0000000 3.3585679 17.504256 79.565237 1.2368237 +30.2000 1 -21884.266 60.648720 3.2078059 1.2719046 -6.9769839 0.0000000 11.872841 34.993443 52.820538 127.88129 737.92218 1.2385385 +30.4000 1 -21838.072 42.342094 -10.052099 4.7715025 -4.2231470 0.0000000 5.6580373 9.5466679 10.483363 13.039130 20.303413 1.2359902 +30.6000 4 -21830.721 -11.241283 10.962642 1.9254584 -5.6357205 -3.6840723 -1.2299002 -0.11672543 0.0000000 0.62018554 3.1247934 1.2385119 +30.8000 5 -21735.453 -27.662830 1.2563350 -0.092399314 1.7932358 4.3301568 6.8564503 5.2554583 3.5152282 0.0000000 -4.2878522 1.2354574 +31.0000 4 -21708.557 4.3383045 -0.49179566 4.2412667 7.3091811 4.7504973 1.3712088 -0.44990313 0.0000000 2.2799428 7.7753704 1.2341096 +31.2000 3 -21706.148 -2.5979862 18.489197 1.3619437 -2.8994701 -2.6998095 -2.2764844 0.0000000 2.4287808 10.896241 35.932578 1.2332679 +31.4000 2 -21838.996 -6.7730618 12.745865 7.5210881 1.3279608 -0.24644480 0.0000000 13.943733 28.111197 86.124190 512.62171 1.2372948 +31.6000 2 -21796.838 1.2540092 41.465458 7.6391110 -8.8900526 -7.0325322 0.0000000 30.126038 54.380798 134.43389 439.58669 1.2359791 +31.8000 1 -21801.604 74.492973 6.6192427 6.2984128 -9.7087335 0.0000000 15.067415 38.952989 53.267486 96.941428 235.39764 1.2362982 +32.0000 0 -21852.184 311.99313 5.5937161 8.8379755 0.0000000 24.423827 54.547426 111.10688 155.50616 351.96223 3036.7315 1.2366153 +32.2000 0 -21877.020 118.48170 -8.9996767 6.2979212 0.0000000 9.8749961 22.132236 29.362846 30.257577 32.004706 38.427570 1.2338431 +32.4000 1 -21902.309 62.501816 4.4092832 3.5417564 -7.2506300 0.0000000 14.250764 51.459124 81.612711 198.22364 992.45710 1.2335951 +32.6000 1 -21873.391 -7.1446228 0.83364159 4.0335288 0.76711275 0.0000000 1.8098936 20.526335 39.183619 116.26001 685.81505 1.2350427 +32.8000 2 -21866.176 -4.1469765 15.047733 7.2734509 -0.37789161 -1.3162197 0.0000000 14.233256 26.116832 61.697785 159.30268 1.2323024 +33.0000 2 -21860.113 -2.4437065 6.7346325 7.9599295 -0.49728134 -1.0256763 0.0000000 8.7723458 15.748969 36.137923 93.935835 1.2330413 +33.2000 3 -21921.570 1.7537918 3.4973006 5.4586787 0.68934847 -0.21651947 -1.1007842 0.0000000 1.4341618 5.5432201 14.182767 1.2319285 +33.4000 3 -21975.277 -5.0042725 2.2646685 -1.2731032 -0.74396520 -0.38801722 0.44813296 0.0000000 -0.40122267 -0.60871765 1.1749116 1.2320573 +33.6000 4 -21961.164 -12.607944 16.421272 2.3064306 -7.9715184 -5.6574470 -2.5374887 -0.50604889 0.0000000 1.5211949 5.7036801 1.2314523 +33.8000 3 -22028.164 0.48733711 6.8189793 0.0055103302 3.9884383 2.2616985 0.16668497 0.0000000 1.1140443 4.7208229 12.168088 1.2302396 +34.0000 2 -21980.924 13.641121 50.457306 1.7238158 -15.376917 -10.870423 0.0000000 34.392675 60.966320 151.30415 582.61963 1.2278129 +34.2000 1 -22046.451 73.169991 12.851662 0.23444954 -9.7141730 0.0000000 15.583973 50.530572 76.583332 165.70600 559.58622 1.2333676 +34.4000 0 -22033.508 165.04825 -2.7668638 0.46863952 0.0000000 13.370103 32.654910 79.276286 121.13423 308.56987 2231.5503 1.2329630 +34.6000 0 -22043.773 212.84607 -6.4278007 1.5405426 0.0000000 16.503308 35.024889 48.270315 52.122648 61.884004 88.117709 1.2332076 +34.8000 0 -22022.768 47.199120 -11.488570 3.5108857 0.0000000 3.5630772 8.6968591 12.847634 13.969084 16.548014 22.314886 1.2308211 +35.0000 4 -21992.430 -8.3513260 -10.201791 0.56847459 4.0284305 4.5093023 4.4935812 1.6484207 0.0000000 -2.9667063 -6.1694613 1.2323319 +35.2000 5 -22036.250 -21.376938 3.6785278 -0.49553779 2.5379347 4.2925264 5.8541389 4.0721500 2.6225981 0.0000000 -2.5051941 1.2338355 +35.4000 3 -22132.070 -3.1464386 10.635343 4.4384151 -1.0928888 -1.3484130 -1.4637857 0.0000000 1.6457038 6.9131153 20.497800 1.2353671 +35.6000 4 -22198.619 -7.2326603 -3.4745138 0.55535150 1.8951973 2.4371945 2.6694661 0.96399092 0.0000000 -1.5257608 -2.6283429 1.2337148 +35.8000 5 -22205.510 -32.857925 9.9564734 -0.33632538 -3.0199548 0.42797262 4.3737732 4.3051751 2.9752170 0.0000000 -3.8809797 1.2356049 +36.0000 5 -22190.152 -37.942230 9.4622641 -0.39032599 -1.7030932 1.9540462 6.2029705 5.5988432 3.8095147 0.0000000 -4.5505106 1.2388729 +36.2000 5 -22172.162 -35.154709 -3.6615133 0.34083995 2.3579807 5.6595417 9.2885198 7.4493831 5.0388551 0.0000000 -6.2690702 1.2404239 +36.4000 6 -22211.645 -252.26913 -3.5780051 1.7850888 8.1990735 26.347294 43.039958 44.132270 39.335803 26.079147 0.0000000 1.2431822 +36.6000 6 -22313.127 -92.010986 -4.7690406 -0.051394314 10.194432 17.203115 25.135089 24.168084 20.651715 12.320115 0.0000000 1.2391193 +36.8000 6 -22269.947 -166.60225 0.13017327 -0.30996865 10.643987 23.259468 36.900088 36.935371 32.111813 19.893888 0.0000000 1.2358526 +37.0000 6 -22252.744 -364.43127 15.029972 -0.74869919 7.3897559 34.221936 60.036838 62.843084 56.093950 37.030679 0.0000000 1.2342010 +37.2000 6 -22177.102 -303.12433 -3.4801269 -0.44341502 11.041112 34.151791 57.597744 59.525879 52.692714 34.024315 0.0000000 1.2323531 +37.4000 6 -22161.293 -334.51712 14.744122 0.55278879 3.9081941 28.343200 51.870990 55.165524 49.334268 32.729025 0.0000000 1.2296368 +37.6000 6 -22115.332 -278.61365 9.6014032 -0.097044036 5.2884629 27.196142 50.448163 53.578750 47.398277 30.358217 0.0000000 1.2353706 +37.8000 6 -22181.135 -187.99533 21.480015 7.2872696 -3.9127856 11.743307 30.243903 34.607907 30.580105 19.141910 0.0000000 1.2353141 +38.0000 0 -22221.807 82.610542 -13.612996 8.0843716 0.0000000 7.0453854 18.008154 33.946662 44.418152 86.631226 360.93231 1.2375604 +38.2000 1 -22148.781 11.318096 -6.2576361 0.096817270 -0.32536738 0.0000000 1.6466082 8.8416416 14.800336 33.297355 85.496191 1.2389101 +38.4000 2 -22090.211 -1.9692574 -1.9311216 0.57977444 4.0118406 2.0046868 0.0000000 2.8494322 6.1910715 15.142123 32.221116 1.2418271 +38.6000 4 -22121.377 -1.4616909 5.1459484 -0.28415945 3.4784554 2.5100728 1.1353738 -0.097860649 0.0000000 1.3662548 5.8068971 1.2389340 +38.8000 4 -22158.203 0.81141281 7.6418972 -0.17814794 4.0413592 2.6801603 0.62744601 -0.49628407 0.0000000 2.2799695 8.0283047 1.2391785 +39.0000 3 -22048.262 0.61543083 16.805468 1.1131349 1.9643097 0.23187507 -1.6591149 0.0000000 2.5123374 9.7769143 24.866191 1.2360367 +39.2000 2 -22024.387 10.119415 -4.0255690 8.3236160 -5.3428951 -3.2944060 0.0000000 4.3444897 6.4816438 12.238227 26.207145 1.2351605 +39.4000 2 -21921.492 -0.68444824 20.330339 3.2584622 -2.1322412 -2.2759402 0.0000000 17.684260 33.918494 93.472316 393.19731 1.2354096 +39.6000 2 -21938.838 -3.1535721 25.131424 0.73221582 -1.1471583 -1.8693458 0.0000000 18.320921 34.681021 89.116604 293.76136 1.2316685 +39.8000 1 -21892.602 23.819403 8.6714106 0.25789183 -3.1031805 0.0000000 7.9068214 35.201313 56.801231 129.25299 445.20497 1.2319181 +40.0000 1 -21910.588 27.300243 1.5008779 7.0732670 -3.6332932 0.0000000 7.5576383 29.106657 46.781262 114.75783 553.76919 1.2348593 diff --git a/ensemble_md/tests/data/dhdl/forced-swap/dhdl_2.xvg b/ensemble_md/tests/data/dhdl/forced-swap/dhdl_2.xvg new file mode 100644 index 0000000..ce322e0 --- /dev/null +++ b/ensemble_md/tests/data/dhdl/forced-swap/dhdl_2.xvg @@ -0,0 +1,238 @@ +# This file was created Sun Jan 19 05:14:48 2025 +# Created by: +# :-) GROMACS - gmx mdrun, 2022.5-dev (-: +# +# Executable: /projects/anfr8476/pkgs/gromacs-2022.5-wl/bin/gmx +# Data prefix: /projects/anfr8476/pkgs/gromacs-2022.5-wl +# Working dir: /gpfs/alpine1/scratch/anfr8476/EEXE/test_forced_swap/small_mol/forced_random/solv/rep1/sim_2/iteration_0 +# Command line: +# gmx mdrun -s sys_EE.tpr -ntomp 6 -ntmpi 1 +# gmx mdrun is part of G R O M A C S: +# +# Great Red Owns Many ACres of Sand +# +@ title "dH/d\xl\f{} and \xD\f{}H" +@ xaxis label "Time (ps)" +@ yaxis label "dH/d\xl\f{} and \xD\f{}H (kJ/mol [\xl\f{}]\S-1\N)" +@TYPE xy +@ subtitle "T = 300 (K) " +@ view 0.15, 0.15, 0.75, 0.85 +@ legend on +@ legend box on +@ legend loctype view +@ legend 0.78, 0.8 +@ legend length 2 +@ s0 legend "Thermodynamic state" +@ s1 legend "Total Energy (kJ/mol)" +@ s2 legend "dH/d\xl\f{} coul-lambda = 0.0000" +@ s3 legend "dH/d\xl\f{} vdw-lambda = 0.0000" +@ s4 legend "dH/d\xl\f{} bonded-lambda = 0.0000" +@ s5 legend "\xD\f{}H \xl\f{} to (0.0000, 0.0000, 0.0000)" +@ s6 legend "\xD\f{}H \xl\f{} to (0.1000, 0.1000, 0.1000)" +@ s7 legend "\xD\f{}H \xl\f{} to (0.3000, 0.3000, 0.3000)" +@ s8 legend "\xD\f{}H \xl\f{} to (0.6000, 0.6000, 0.6000)" +@ s9 legend "\xD\f{}H \xl\f{} to (0.7000, 0.7000, 0.7000)" +@ s10 legend "\xD\f{}H \xl\f{} to (0.8500, 0.8500, 0.8500)" +@ s11 legend "\xD\f{}H \xl\f{} to (1.0000, 1.0000, 1.0000)" +@ s12 legend "pV (kJ/mol)" +0.0000 0 -22229.930 218.24573 2.6204460 1.2559161 0.0000000 18.859226 45.813426 87.901436 114.13203 207.21330 713.99455 1.2297791 +0.2000 0 -22205.363 208.35834 10.282860 -0.46683121 0.0000000 18.773513 48.903528 117.83817 173.41451 416.95430 5640.4134 1.2313271 +0.4000 0 -22230.637 288.71664 1.9099225 6.2252722 0.0000000 22.920607 50.550151 83.746708 101.03598 164.57543 715.17532 1.2311585 +0.6000 0 -22256.014 239.57758 -2.9888496 1.7805481 0.0000000 19.399810 46.887735 96.619556 129.08773 236.28088 700.56508 1.2288349 +0.8000 0 -22239.547 105.53345 -12.514267 0.61477399 0.0000000 8.8697797 25.488627 59.626191 81.801600 160.68930 729.38869 1.2288287 +1.0000 1 -22261.324 55.237103 2.2850833 8.2886038 -6.6394514 0.0000000 13.019698 34.932585 45.041960 67.872859 113.58219 1.2288629 +1.2000 2 -22209.996 32.706604 -22.406910 1.4253063 9.3961608 2.4503953 0.0000000 11.537623 19.771396 40.603308 87.112774 1.2313678 +1.4000 3 -22329.201 13.858295 -2.8904102 0.95646811 36.308473 13.125441 -0.087635827 0.0000000 1.4073306 4.5250042 10.640149 1.2337381 +1.6000 4 -22306.979 11.701923 23.073025 2.1789384 153.65580 42.207338 -0.45141762 -2.9801425 0.0000000 7.5745095 22.724420 1.2336458 +1.8000 3 -22244.703 22.004276 -15.585249 -1.1995517 44.151619 21.879227 4.6925500 0.0000000 1.0414094 4.5935347 11.360973 1.2354945 +2.0000 4 -22306.426 -4.5027390 24.232349 -2.4699616 32.138003 7.0016324 -3.8031952 -1.5853358 0.0000000 3.2151428 9.6806862 1.2341338 +2.2000 3 -22317.412 20.362465 13.965128 3.7716851 -12.548105 -12.440090 -9.1270155 0.0000000 4.1561360 12.219230 24.559145 1.2325066 +2.4000 1 -22306.918 103.61987 4.3474803 5.9716368 -13.110865 0.0000000 19.502790 49.707333 65.569650 108.25851 226.36818 1.2296395 +2.6000 0 -22324.969 121.58904 -20.497364 3.5760839 0.0000000 9.9136790 28.329840 66.179999 90.275721 164.64679 424.78340 1.2265056 +2.8000 1 -22332.738 58.384182 -0.60497314 5.1905093 -6.2027777 0.0000000 13.098967 41.228370 59.346205 119.75625 384.28868 1.2263284 +3.0000 1 -22332.980 30.481979 -0.13433336 -4.1232195 -2.2188489 0.0000000 6.8599867 28.987775 46.256701 114.99394 701.44960 1.2305089 +3.2000 2 -22313.848 26.658123 -9.6989803 -4.0424047 1.4282412 -0.65817742 0.0000000 6.6332803 10.187189 17.781921 30.863965 1.2274879 +3.4000 5 -22308.262 10.491768 25.791862 2.1697690 2697.8922 261.55918 29.832623 -2.5453973 -3.2236068 0.0000000 9.1386496 1.2223725 +3.6000 3 -22305.697 23.076103 -40.103416 0.84590435 443.27052 123.83408 22.538939 0.0000000 -0.62094350 1.5973681 7.8747313 1.2241163 +3.8000 4 -22196.469 16.814358 -5.1084037 -0.35800517 37.832688 18.847752 3.3632853 -0.74888367 0.0000000 2.6314050 7.9783328 1.2251625 +4.0000 4 -22190.674 15.194996 -55.306274 -0.53810000 2561.2921 403.85756 71.037518 5.6667630 0.0000000 -3.5356917 -3.0377415 1.2209755 +4.2000 5 -22125.629 -15.167953 -16.080685 -1.6441188 309.80850 137.62997 43.451955 9.8985528 5.3041776 0.0000000 -5.0546583 1.2205609 +4.4000 6 -22229.164 -119.10440 -7.6674023 -6.0601873 1587.1566 378.61060 106.12447 37.531781 28.103510 15.661979 0.0000000 1.2238185 +4.6000 6 -22168.449 -52.067932 -2.3061194 -5.9333982 2142.8717 399.36010 86.982575 24.779020 17.279776 8.5070030 0.0000000 1.2258085 +4.8000 6 -22161.113 -21.592209 18.569584 -2.9750977 41.299437 23.750326 8.8521398 2.6829465 1.8976612 0.94745540 0.0000000 1.2248449 +5.0000 5 -22186.768 13.513596 -2.5364523 -4.7661610 326.11408 142.99257 39.025471 3.9771301 0.92218659 0.0000000 2.7999509 1.2275493 +5.2000 4 -22153.631 16.701382 -2.0220103 0.88112688 43.520647 21.865484 3.7022631 -1.0561237 0.0000000 3.5253057 10.315702 1.2273325 +5.4000 3 -22164.879 7.6013794 -0.10489549 -0.20454609 -8.3416905 -7.3967762 -4.0175803 0.0000000 0.46816103 0.11203387 -1.5966476 1.2298583 +5.6000 6 -22097.377 -220.98071 10.801498 -2.9781501 54.969386 42.420442 37.102588 34.093077 30.849319 21.226003 0.0000000 1.2306073 +5.8000 6 -22008.865 -127.90952 -9.1598701 -0.16989028 4506.4039 546.02485 128.60901 42.034807 31.013553 16.858076 0.0000000 1.2310774 +6.0000 6 -22012.480 -285.63190 19.283747 -6.5746722 40457.149 684.74958 137.42398 54.709132 43.684092 27.031114 0.0000000 1.2353274 +6.2000 6 -22017.131 -259.74539 13.096926 -8.8980732 3938.2621 478.57454 119.64719 51.810365 41.951904 26.104946 0.0000000 1.2345593 +6.4000 6 -21892.752 -226.74329 -2.0134413 -1.2790165 473.73477 157.41500 68.005130 45.887635 39.399675 25.150184 0.0000000 1.2363540 +6.6000 6 -21900.189 -133.76651 3.9459107 -7.9401531 674.16528 205.66022 67.724532 30.383781 24.351988 14.850501 0.0000000 1.2421016 +6.8000 6 -21883.699 -212.35028 -2.9705391 -0.23682889 3929.7159 575.03860 139.54037 50.425219 38.790355 22.883550 0.0000000 1.2431760 +7.0000 6 -21814.590 -158.16685 11.751198 4.0920310 268.74830 117.13109 49.579698 27.962565 23.497349 15.000833 0.0000000 1.2439013 +7.2000 6 -21937.041 -209.83299 7.4626598 -9.5195179 81.085527 57.171876 43.473794 35.426872 31.313662 21.041576 0.0000000 1.2438518 +7.4000 6 -21927.719 -231.78506 2.5900064 1.3058635 692.39124 241.03332 84.238042 40.607574 33.641549 21.858946 0.0000000 1.2435430 +7.6000 6 -21890.865 -60.631233 15.993685 -7.7817597 141.81146 77.001361 34.465616 16.980654 13.234092 7.2031077 0.0000000 1.2437321 +7.8000 5 -21773.166 -31.911377 0.66065693 0.94185644 191.22072 94.882827 31.145397 8.0125813 4.5675113 0.0000000 -4.6286227 1.2439415 +8.0000 5 -21791.773 -10.392807 -19.345531 -3.4254546 1180.0172 285.29762 68.129039 12.479950 6.1493698 0.0000000 -4.3902984 1.2419931 +8.2000 6 -21751.738 -71.345665 18.637268 -4.6906099 603.55908 203.97142 60.118012 19.962963 14.473739 7.5486789 0.0000000 1.2439772 +8.4000 5 -21743.703 -2.0731125 11.579226 -0.75531447 5.6992615 -0.10282110 -3.5136517 -2.1185690 -1.2831470 0.0000000 1.4396640 1.2405560 +8.6000 4 -21726.225 -3.4433441 11.410775 -0.37260878 174.52625 63.333613 11.281923 -0.18400952 0.0000000 2.5740585 9.8389853 1.2427518 +8.8000 4 -21721.158 9.1714478 -5.3651485 -5.3703761 120.31889 44.935260 8.6880901 0.37726279 0.0000000 0.11579224 0.90569488 1.2415438 +9.0000 5 -21675.189 19.010048 -3.3717995 -8.8446875 41.765897 23.479971 6.6997257 -0.19589330 -0.51553938 0.0000000 1.4941465 1.2392037 +9.2000 3 -21650.250 21.124290 -27.874073 -7.3205605 165.51857 67.523562 14.733645 0.0000000 -0.88198306 -0.79791609 0.40769858 1.2413040 +9.4000 5 -21633.895 20.269405 -9.3246632 -7.5398908 162.01007 89.870292 29.772469 3.6401599 1.0078012 0.0000000 2.0331267 1.2432632 +9.6000 5 -21690.762 20.764458 1.1242174 -4.6425223 42.935799 20.540481 3.2089624 -2.1160912 -1.7871573 0.0000000 3.6093276 1.2472202 +9.8000 4 -21723.754 10.131859 59.314743 -0.47434390 -2.2161015 -10.667084 -13.643213 -5.6442946 0.0000000 15.452957 57.710357 1.2436461 +10.0000 2 -21782.586 30.137154 -36.644592 -2.8526955 15.810752 6.5818475 0.0000000 3.4437261 7.2351145 16.999916 37.795494 1.2451521 +10.2000 3 -21804.305 17.702679 17.493467 0.30263093 -17.137001 -14.848436 -9.4911939 0.0000000 3.7559011 10.514755 19.754378 1.2445583 +10.4000 2 -21773.236 24.414154 8.4731760 0.62954956 -7.6602420 -5.6487441 0.0000000 13.303532 20.019114 34.631542 60.832470 1.2441500 +10.6000 1 -21714.117 56.653481 -8.1368341 1.9876223 -5.1562577 0.0000000 9.2788035 19.238645 21.557806 24.509383 27.711128 1.2504126 +10.8000 2 -21688.232 33.664814 -25.464994 0.20791900 19.386735 5.1423256 0.0000000 9.9360134 16.807094 34.224223 73.751895 1.2488562 +11.0000 2 -21728.277 29.358841 9.5144329 7.8190613 -6.4424566 -7.0224968 0.0000000 18.340431 27.622365 48.894001 91.746970 1.2533779 +11.2000 1 -21791.852 78.221924 5.7401571 8.9794254 -9.7967227 0.0000000 17.902554 53.654869 76.650577 156.96138 694.74102 1.2527267 +11.4000 0 -21865.541 279.17050 -13.823784 7.8735180 0.0000000 19.758218 40.430724 58.299328 63.194651 70.431351 75.662737 1.2538754 +11.6000 0 -21884.439 136.83829 -8.8692560 4.2049465 0.0000000 11.816405 31.233981 68.442053 95.452201 224.59998 4713.5211 1.2567953 +11.8000 0 -21928.758 98.372192 -4.5726948 1.0194273 0.0000000 8.9897831 26.062579 64.174401 89.664652 168.54934 424.75661 1.2600106 +12.0000 0 -21879.672 180.57620 -19.334806 -4.1880736 0.0000000 14.098310 35.004585 62.478531 80.246895 169.72475 2001.1669 1.2533718 +12.2000 0 -21784.383 332.63208 -10.046557 -2.7338796 0.0000000 24.790271 51.453145 64.611595 63.666897 56.249881 35.979922 1.2543120 +12.4000 0 -21816.199 145.70749 -1.2997959 6.6671190 0.0000000 13.532485 35.364923 72.070459 93.489087 159.15008 409.17240 1.2508545 +12.6000 1 -21815.840 100.59715 -8.4264669 7.1533070 -10.634533 0.0000000 17.744742 43.534348 57.953439 112.19900 518.00877 1.2514157 +12.8000 0 -21808.227 448.65826 1.2764235 2.7422194 0.0000000 33.230466 68.614045 104.21079 118.61733 151.79986 220.10385 1.2510364 +13.0000 0 -21776.900 219.29980 -4.2562804 8.8010054 0.0000000 18.841478 44.582467 75.128975 88.985347 127.68739 256.52086 1.2515596 +13.2000 0 -21745.422 216.69798 -4.1882081 -0.52482229 0.0000000 17.930673 40.929164 57.543079 60.111498 62.722800 69.014839 1.2514721 +13.4000 0 -21813.197 282.82748 3.1590033 4.5118246 0.0000000 23.226364 51.470764 76.635108 83.973811 98.234379 128.56887 1.2503116 +13.6000 0 -21876.664 376.12167 -6.4623737 8.5872040 0.0000000 30.190901 69.758376 139.42102 194.99193 478.33391 98620.133 1.2477735 +13.8000 0 -21854.418 277.73145 -30.500566 -2.7245345 0.0000000 18.271276 37.494257 50.175020 52.169740 54.426979 59.120872 1.2476182 +14.0000 0 -21801.295 166.27893 -16.014095 -0.80439532 0.0000000 12.717049 31.205299 61.338029 82.981440 190.85717 3045.0000 1.2490889 +14.2000 0 -21808.836 181.87732 -2.5311611 5.2772131 0.0000000 16.150426 39.430902 69.375867 86.613521 162.13742 1184.7861 1.2497215 +14.4000 0 -21802.014 109.76122 -7.5128775 7.2553558 0.0000000 10.194198 27.422319 52.863171 65.170736 98.991458 212.36920 1.2464297 +14.6000 0 -21801.287 201.88766 0.64619547 0.26696327 0.0000000 16.628287 39.055294 72.821440 95.075085 185.93163 875.14998 1.2454405 +14.8000 0 -21784.266 250.09790 -5.2467885 3.0213943 0.0000000 20.156264 44.376159 61.803018 65.455095 73.903691 109.82104 1.2453138 +15.0000 0 -21769.020 109.88745 -4.5046945 6.3322868 0.0000000 10.336766 26.995190 47.261296 55.244895 74.481011 124.10666 1.2440488 +15.2000 0 -21782.256 193.84950 -3.1784306 8.1663218 0.0000000 17.266388 41.001113 62.186613 68.045098 80.177976 110.86821 1.2438400 +15.4000 1 -21804.031 62.946476 -1.4717655 -2.1428795 -5.9949521 0.0000000 11.891542 35.445155 49.648426 92.914399 245.63540 1.2463167 +15.6000 1 -21707.184 96.433975 -8.5578184 6.0845923 -9.4547025 0.0000000 18.888737 55.345936 75.794598 132.04682 293.24585 1.2477188 +15.8000 0 -21768.541 92.770096 -26.436974 -2.1905489 0.0000000 6.3011520 17.486129 31.848401 37.327692 49.441352 77.610691 1.2472663 +16.0000 1 -21778.863 23.836594 -14.741493 4.8721080 -0.91829080 0.0000000 4.1650652 14.264740 18.693377 26.843569 37.917312 1.2479409 +16.2000 2 -21888.148 33.786804 -21.336323 -0.11031029 6.5232849 0.86547790 0.0000000 7.0108471 10.617275 17.996928 30.112163 1.2508886 +16.4000 4 -21901.805 13.094681 -8.0329390 -1.0871127 56.972234 22.571511 3.2859151 -0.27323062 0.0000000 0.76833972 1.8306248 1.2497323 +16.6000 5 -21919.994 5.0654221 11.705912 -0.022081181 -2.3485407 -6.6114811 -7.4788145 -3.8718085 -2.3769669 0.0000000 2.8056473 1.2503706 +16.8000 3 -21946.180 21.504307 -5.1440406 -0.64964437 141.16417 51.133909 7.0008160 0.0000000 2.5054875 10.181653 25.628632 1.2510087 +17.0000 5 -21957.496 14.055504 0.51356745 -5.0776467 58.305863 26.417574 4.9540656 -0.98116481 -0.93681900 0.0000000 2.0910472 1.2490819 +17.2000 4 -22054.127 20.936440 1.7630144 -4.5810194 5.6807601 0.88651615 -2.9330326 -1.5712279 0.0000000 3.2850550 7.9130056 1.2494178 +17.4000 3 -22050.031 20.960739 14.306608 0.17710003 0.92695263 -5.9120310 -7.1219720 0.0000000 3.9778509 12.054574 24.523861 1.2506371 +17.6000 2 -22007.020 46.784294 1.8987410 -2.0352626 -15.361601 -10.061837 0.0000000 13.016066 17.664110 27.211138 46.364531 1.2550907 +17.8000 1 -22124.363 31.136890 -1.8667667 -1.4381381 -2.0713667 0.0000000 7.4554518 28.747335 43.813109 98.738129 448.44678 1.2564747 +18.0000 2 -22148.543 30.203533 3.8985884 0.40914959 -6.4750095 -5.4765986 0.0000000 13.879911 21.533821 41.689630 96.004359 1.2567405 +18.2000 2 -22125.980 32.176941 -5.3541169 -0.071618140 -8.7515594 -5.6747565 0.0000000 7.4600212 9.8240594 13.614055 18.855929 1.2540205 +18.4000 3 -22145.098 19.430450 8.3622389 -1.5585760 -13.134633 -11.836314 -7.5004780 0.0000000 2.7029257 7.2670437 13.102463 1.2561157 +18.6000 1 -22153.879 46.964020 1.0285598 9.2139378 -5.8682273 0.0000000 11.165593 29.567108 37.654756 54.682895 84.902547 1.2557902 +18.8000 1 -22178.139 75.432114 8.9745264 2.0415206 -8.7068053 0.0000000 18.006929 64.090071 101.44762 272.90652 2935.9586 1.2546358 +19.0000 1 -22191.262 36.931557 1.0152035 9.8390388 -4.4064964 0.0000000 10.929632 35.848951 49.538387 83.284475 159.19073 1.2566957 +19.2000 1 -22113.000 51.474533 8.0882673 5.5301313 -5.7851607 0.0000000 16.514316 74.328782 124.30629 346.60687 4815.4738 1.2562573 +19.4000 1 -22105.355 50.915115 -20.101484 4.7528553 -3.1597979 0.0000000 8.2437357 25.815557 34.569413 54.166400 91.043081 1.2613450 +19.6000 2 -22102.652 27.328121 6.9425120 -1.6953125 -6.9344439 -5.3896357 0.0000000 12.538448 18.554302 30.977635 50.970019 1.2629429 +19.8000 2 -22061.604 27.168839 -35.905212 1.0499706 36.867052 11.552992 0.0000000 7.6004117 14.245012 31.023124 67.707303 1.2621154 +20.0000 3 -22131.719 19.797020 23.127478 6.0770516 -14.427268 -14.632227 -11.073388 0.0000000 5.4696148 16.749229 35.678897 1.2580675 +20.2000 1 -22128.445 31.002522 -6.6794825 -3.1958110 -1.8166624 0.0000000 4.5879365 11.421627 13.681591 17.392184 22.275873 1.2570610 +20.4000 2 -22180.768 24.486534 -5.6584220 1.5949476 -3.7125517 -3.1868671 0.0000000 7.4721275 10.588765 16.181459 23.640009 1.2551553 +20.6000 3 -22224.555 19.846386 20.832701 -2.4663153 -0.85061987 -4.8073020 -6.4834044 0.0000000 4.5117141 14.687496 32.165512 1.2558702 +20.8000 3 -22169.594 20.581200 -0.47624680 -3.3561699 23.997154 10.942227 0.49016541 0.0000000 2.2643395 8.3286765 20.000286 1.2606457 +21.0000 3 -22220.211 19.369766 3.4535327 -2.2309442 10.566036 3.9188333 -1.7273072 0.0000000 2.5658419 8.6989467 19.157426 1.2591640 +21.2000 4 -22142.891 -2.0231094 0.051271867 -7.6201777 1595.7554 202.12964 25.834319 1.5116523 0.0000000 -0.48843714 1.1510630 1.2607158 +21.4000 3 -22125.650 23.049286 -21.468233 -7.1987495 200.85262 86.252945 18.631196 0.0000000 0.62781380 5.8065092 17.082498 1.2607995 +21.6000 4 -22161.570 20.025639 -40.508549 -8.6925192 467.42671 215.91819 58.151452 4.6142495 0.0000000 -1.3268041 2.8277075 1.2620957 +21.8000 5 -22086.801 1.4929657 14.831527 -3.4640999 -1.4155829 -4.6695404 -5.4496866 -2.7866774 -1.7323778 0.0000000 2.3857821 1.2582413 +22.0000 4 -22061.637 24.384167 32.707687 -8.6659250 -2.2810881 -6.5192545 -8.9219893 -4.0205149 0.0000000 9.9010002 29.319048 1.2593402 +22.2000 3 -22067.617 20.522419 7.0282354 -8.9449129 -2.8639069 -4.3646314 -3.9861050 0.0000000 2.0587409 6.0307788 11.497499 1.2619320 +22.4000 4 -21981.191 9.5707321 17.209724 -7.1021276 -15.994738 -13.556355 -8.3018768 -1.9162893 0.0000000 3.3731560 9.1744202 1.2635896 +22.6000 3 -21981.613 16.958271 13.103834 2.8490334 -19.296137 -16.339323 -9.7966337 0.0000000 3.3621190 8.9614461 16.119588 1.2636204 +22.8000 1 -21965.301 76.333092 -1.3270324 6.4568377 -8.7698223 0.0000000 14.332536 33.644520 43.632773 79.374578 291.23207 1.2630064 +23.0000 0 -21981.969 105.32110 2.2956009 -2.3244047 0.0000000 9.6252624 26.053805 59.055578 83.907475 196.23655 1916.3703 1.2663993 +23.2000 1 -21965.271 90.967079 -2.9067557 0.99027711 -9.6478995 0.0000000 15.628579 36.917877 47.637409 82.784375 257.96290 1.2670035 +23.4000 0 -21932.912 140.11026 -2.8791671 -0.61417150 0.0000000 11.968929 29.318410 49.122525 56.702983 73.784344 112.06811 1.2680537 +23.6000 1 -21922.789 52.924301 -11.084902 -1.2456679 -4.1216141 0.0000000 7.6567327 17.486121 20.768958 26.957678 38.116857 1.2712834 +23.8000 1 -21921.297 130.59904 0.39248759 -3.1292963 -15.184765 0.0000000 19.576693 36.399728 40.606000 47.218658 56.627020 1.2728665 +24.0000 0 -22014.615 202.72665 -1.0312803 1.8909816 0.0000000 17.714607 43.655926 79.804711 99.133265 158.30138 386.56298 1.2751713 +24.2000 0 -21979.387 253.38432 -14.278951 8.0579510 0.0000000 19.490397 42.611340 62.157024 67.560761 79.191191 113.99052 1.2755244 +24.4000 0 -21935.420 173.38754 -8.9145870 2.9121103 0.0000000 14.466892 33.811660 48.404537 50.701667 52.870710 56.094353 1.2726045 +24.6000 0 -21912.572 537.42310 5.4228892 3.6441720 0.0000000 38.548239 76.038025 107.57711 120.60468 168.50719 584.55293 1.2742237 +24.8000 0 -21867.660 371.31161 1.8665738 5.8858018 0.0000000 29.243729 63.124888 98.021795 113.67211 161.29269 359.41174 1.2741480 +25.0000 0 -21826.406 295.58459 -1.4471720 -0.29693127 0.0000000 22.711018 49.418467 76.502414 86.815207 110.78392 167.17232 1.2699603 +25.2000 0 -21847.168 161.17200 3.0096419 5.0155420 0.0000000 15.090026 38.413150 73.814545 94.405558 163.20364 468.53509 1.2670580 +25.4000 0 -21771.566 135.41562 2.8562891 9.0037813 0.0000000 13.450388 35.042789 66.074516 82.125798 130.25995 315.04622 1.2629131 +25.6000 1 -21701.930 116.10349 -20.155798 4.4622307 -11.960003 0.0000000 15.040818 24.338647 24.356011 20.879752 11.081453 1.2602016 +25.8000 0 -21823.941 101.31375 -6.4072661 5.4899912 0.0000000 9.0773948 22.555045 33.934966 35.730400 36.691678 35.645777 1.2614367 +26.0000 1 -21965.199 101.94560 8.0477800 9.5089703 -13.332797 0.0000000 20.384865 46.761934 58.244687 86.269460 154.34626 1.2581381 +26.2000 0 -22058.152 168.02504 -20.746521 1.4023414 0.0000000 12.604037 31.217795 64.946449 90.221126 211.33592 3271.5405 1.2619902 +26.4000 1 -21987.391 57.625828 -15.200468 2.6910677 -3.9693456 0.0000000 9.8357421 27.464536 36.053432 58.191005 119.60971 1.2619710 +26.6000 1 -22016.789 42.063393 1.9997479 -1.6636523 -4.1023250 0.0000000 9.1398918 28.869989 39.985494 69.149106 145.12706 1.2583526 +26.8000 2 -22008.188 30.327633 7.7270513 9.3754025 -10.993116 -8.1758404 0.0000000 18.131304 27.260435 48.122991 90.279568 1.2588763 +27.0000 1 -22073.395 33.126652 -15.126566 -0.79897821 -1.1539160 0.0000000 4.9199746 17.642329 24.546009 41.071267 75.346289 1.2627124 +27.2000 2 -22074.635 28.832439 1.6139104 5.5022202 -8.3992192 -6.2179506 0.0000000 13.372703 19.636780 32.625585 54.303523 1.2608254 +27.4000 3 -22044.168 17.871758 20.592340 2.9973345 -11.895309 -12.217903 -9.3822299 0.0000000 4.6084360 13.928816 28.576223 1.2600847 +27.6000 2 -22054.500 27.409111 -1.4161060 -0.98728967 -5.6273648 -4.2608539 0.0000000 9.2856576 13.655548 22.943863 39.912231 1.2601701 +27.8000 1 -21981.021 81.572067 -12.512465 4.0607796 -7.7288626 0.0000000 13.532131 34.899354 45.935855 78.296199 202.73965 1.2600423 +28.0000 2 -21936.191 27.736443 1.5665858 -7.4534650 -2.4413660 -2.7463746 0.0000000 10.561924 17.044478 33.839597 74.130551 1.2625722 +28.2000 3 -21965.715 11.881660 80.200165 0.44344416 -26.873892 -25.613888 -18.936208 0.0000000 11.078268 39.744698 113.31663 1.2676173 +28.4000 2 -21988.078 30.697865 17.051867 -0.81659460 2.1608952 -3.1572603 0.0000000 31.823601 57.756196 143.29639 462.59142 1.2687993 +28.6000 2 -21980.207 24.927101 10.673171 1.7212650 -7.8235596 -5.9742354 0.0000000 16.766266 27.334295 58.287591 164.23792 1.2652948 +28.8000 2 -22048.102 29.663780 -9.4687977 -0.13441443 -0.63898617 -1.9183197 0.0000000 9.9093290 15.340818 27.043436 46.650603 1.2637447 +29.0000 3 -22000.217 17.371677 4.4811726 -1.9172497 3.5516944 -0.73246869 -3.2631104 0.0000000 2.2951397 7.1379519 14.783285 1.2645743 +29.2000 4 -22031.068 18.031525 20.900726 -1.0895507 75.712153 21.459699 -3.0136213 -3.1076423 0.0000000 7.5869509 21.399648 1.2621943 +29.4000 3 -21933.986 20.013123 35.876434 -0.67375410 2.4261413 -5.8439500 -9.1595595 0.0000000 6.5931690 22.131841 52.385211 1.2651956 +29.6000 2 -21975.164 20.259262 -5.8237882 -6.6375203 2.4153277 0.35521864 0.0000000 6.4570116 11.218705 24.275311 60.458061 1.2653172 +29.8000 4 -21857.467 16.506516 2.1253171 0.31517574 -5.6735137 -7.0306619 -6.2766472 -1.8324612 0.0000000 2.9965538 6.4176146 1.2639668 +30.0000 3 -21878.193 20.972187 -10.484531 -7.1848431 141.37881 57.121415 10.997937 0.0000000 1.2386581 6.6480351 18.517007 1.2613536 +30.2000 4 -21940.146 11.183998 -2.0761142 -1.8621101 240.94174 80.355580 14.324606 -0.067369121 0.0000000 2.4844899 8.3989419 1.2611339 +30.4000 5 -21968.947 -10.028664 24.739527 -8.8661442 165.80518 63.900274 14.663777 1.0616544 0.032839199 0.0000000 2.1176353 1.2593117 +30.6000 4 -22074.141 5.2040253 -3.5602365 -0.28842205 73.660305 30.764155 5.2608173 -0.014301809 0.0000000 0.36204800 1.1087052 1.2570441 +30.8000 5 -22065.398 3.2358475 16.318958 -5.7512922 51.522080 22.664703 3.4279018 -1.6655686 -1.4154506 0.0000000 2.9602085 1.2573154 +31.0000 4 -22124.619 10.065620 12.019307 -0.065064192 26.157514 6.5290292 -3.5613757 -1.9085992 0.0000000 4.2785253 12.691595 1.2609040 +31.2000 3 -22132.664 11.627266 -9.3741970 -0.28322005 9.0566496 3.1113423 -0.37113980 0.0000000 0.099932123 -0.24979966 -1.3067077 1.2612391 +31.4000 5 -22201.943 8.6634674 8.0186653 -4.7706876 157.25265 60.161301 12.088313 -0.43653412 -0.90225479 0.0000000 2.8179423 1.2576187 +31.6000 4 -22189.064 3.4328384 -8.5450583 0.50743848 83.913802 36.287664 7.8853416 0.54498410 0.0000000 -0.76286302 -2.1330945 1.2586014 +31.8000 3 -22198.961 13.066826 19.967117 -0.42550027 -14.951128 -13.423872 -8.6806445 0.0000000 3.5241709 10.594102 22.902559 1.2566214 +32.0000 2 -22193.277 21.930611 4.5421085 -3.6817164 -3.7183448 -3.4260697 0.0000000 9.1212913 13.634171 23.282058 40.554541 1.2541524 +32.2000 3 -22166.436 17.068310 -21.398170 -0.63741410 136.27726 52.141619 10.008081 0.0000000 -0.043821590 1.3073657 4.7560071 1.2540524 +32.4000 5 -22135.320 10.974533 16.719557 -1.7547179 11.936655 2.2697208 -4.7657096 -4.5498156 -3.1556050 0.0000000 4.8896061 1.2568736 +32.6000 4 -22104.953 17.632843 1.0721266 5.6794915 64.347356 21.794751 -0.72341606 -2.0489103 0.0000000 4.5187581 11.105990 1.2568136 +32.8000 3 -22134.031 21.567322 27.349319 2.1698098 -1.6100384 -6.8633381 -8.7290237 0.0000000 6.1710815 21.760719 57.209507 1.2555925 +33.0000 2 -22078.734 40.210175 6.4872990 6.4200001 -19.565523 -12.145292 0.0000000 13.732649 18.120589 27.477990 61.534670 1.2485954 +33.2000 1 -22082.484 45.455383 -7.9783483 2.6967485 -3.8170126 0.0000000 8.2694618 21.786586 27.691227 41.239396 71.952336 1.2509042 +33.4000 2 -21984.957 30.379135 8.0665092 5.2723751 -12.495089 -8.5169729 0.0000000 14.615320 21.266025 36.564630 70.465304 1.2546775 +33.6000 1 -22014.791 36.936073 -0.75644952 3.2864892 -3.7461417 0.0000000 8.6235167 26.064346 34.543981 52.855766 84.623563 1.2556832 +33.8000 2 -21974.180 26.083317 3.9184577 2.5730920 -5.2867453 -4.7995366 0.0000000 13.548498 20.522379 35.794259 63.978378 1.2596838 +34.0000 2 -21965.098 25.943695 52.593189 1.7163110 -17.094490 -12.592544 0.0000000 43.197110 78.993763 237.15886 4642.1403 1.2560785 +34.2000 0 -22030.559 67.746574 2.8251462 4.1984100 0.0000000 7.4014859 22.229672 51.245029 67.366364 109.86856 216.84361 1.2578219 +34.4000 1 -22054.281 36.166786 3.8340495 -0.63414454 -3.4310923 0.0000000 9.6133787 34.318073 49.136489 89.087410 199.63866 1.2544568 +34.6000 2 -21908.514 48.657913 8.8262777 0.20022452 -12.107952 -9.2424254 0.0000000 28.501734 50.819616 139.61811 773.30269 1.2570556 +34.8000 1 -21975.824 63.455761 -19.356981 3.9033613 -4.6658623 0.0000000 9.7472186 25.506672 32.254023 46.875595 75.253881 1.2563829 +35.0000 1 -22010.242 42.247982 -1.0883741 6.6641321 -4.6044711 0.0000000 10.181695 30.599733 41.678211 71.708138 161.43350 1.2578952 +35.2000 1 -22052.418 67.216034 -9.8748322 2.7075682 -6.3518792 0.0000000 10.839216 24.923323 30.376401 42.803365 73.572860 1.2575318 +35.4000 1 -22049.785 39.033634 -18.842142 4.2527571 -1.9668983 0.0000000 6.2784907 20.794815 27.839773 42.685669 67.747712 1.2554957 +35.6000 2 -22102.301 28.615913 -15.691750 6.7926092 -0.94202837 -2.0489911 0.0000000 9.0166782 13.632314 23.396114 41.083292 1.2562762 +35.8000 2 -22120.326 24.114765 14.221742 8.8435011 -12.924505 -8.8713414 0.0000000 16.654993 24.311610 40.442872 68.715827 1.2572756 +36.0000 1 -22077.553 33.753830 -0.047506493 9.0374603 -4.2007919 0.0000000 8.8299914 24.634523 31.815736 47.139987 74.624317 1.2523855 +36.2000 2 -22081.473 37.126740 3.5432026 8.1937599 -16.310898 -10.514238 0.0000000 13.401255 17.657935 24.720828 34.386665 1.2506764 +36.4000 1 -22059.414 40.955437 2.7920687 8.1873770 -5.0731209 0.0000000 10.877316 31.824296 42.745776 71.709565 159.06799 1.2536902 +36.6000 1 -22092.133 48.596184 3.8887291 -1.0591352 -4.9435833 0.0000000 10.733391 32.951900 48.082062 110.50513 701.47233 1.2546099 +36.8000 1 -22063.188 91.966225 -8.1729670 8.7200031 -10.816281 0.0000000 14.603131 27.367509 29.824250 31.635915 29.886781 1.2537042 +37.0000 0 -22093.230 349.68079 -4.6646948 0.75275141 0.0000000 27.172555 61.983981 117.32411 155.99305 316.92963 2719.1914 1.2508076 +37.2000 0 -22062.090 88.439613 -3.6965756 -1.0941854 0.0000000 7.9857794 21.635734 40.122822 48.220031 68.270314 117.21779 1.2515447 +37.4000 1 -22006.498 86.645996 -62.557011 -1.1392605 -1.2513364 0.0000000 6.0101039 15.164178 18.290760 24.853130 39.577070 1.2474070 +37.6000 3 -22049.596 19.039383 7.6888409 -0.35300159 -9.6347276 -9.3781328 -6.6821771 0.0000000 2.8059408 7.8746733 14.803300 1.2503835 +37.8000 4 -22028.574 2.3416748 2.4694943 0.99237692 -16.757473 -13.254901 -6.8831810 -0.86733541 0.0000000 0.25802100 -0.52576707 1.2495443 +38.0000 2 -22057.365 29.606148 1.7928193 2.7466183 -8.9999758 -6.3198170 0.0000000 12.016498 17.558404 29.653741 52.930687 1.2516853 +38.2000 2 -22064.713 32.748055 2.9657340 0.23702455 -9.6701290 -6.7358828 0.0000000 12.804431 19.236080 35.714443 79.781547 1.2530559 +38.4000 1 -22090.770 54.555981 -2.6447699 -1.3439122 -5.3404503 0.0000000 9.0312930 19.538796 22.873720 29.094048 40.352932 1.2529858 +38.6000 2 -22070.357 21.675865 5.3523250 -1.2047116 -1.3316145 -2.4519247 0.0000000 16.305884 29.508620 78.755234 389.00783 1.2512749 +38.8000 2 -22039.547 20.076767 22.763205 3.5645103 -3.1868235 -4.5985131 0.0000000 31.272002 59.444676 191.59284 4184.6458 1.2500536 +39.0000 2 -21972.799 22.929813 41.360905 -1.3983078 -10.884678 -8.8827361 0.0000000 34.775906 61.423565 153.46286 704.73513 1.2441899 +39.2000 1 -22037.760 80.308319 -1.1780117 -4.3459435 -7.7729616 0.0000000 13.995329 36.004544 46.712786 73.309028 135.17701 1.2468691 +39.4000 1 -22001.330 86.335846 -2.1425831 -1.2741791 -9.2430168 0.0000000 13.688681 27.346334 31.661416 41.688546 70.906357 1.2472504 +39.6000 0 -22007.584 242.46986 -20.903175 5.6028118 0.0000000 19.744502 49.858675 105.17608 145.99634 329.35671 5936.4137 1.2423795 +39.8000 0 -22021.033 199.35599 -14.285631 9.0239553 0.0000000 16.862479 39.963823 58.785202 62.264845 65.900988 69.129465 1.2467736 +40.0000 0 -21966.773 211.88077 -27.419308 8.8746595 0.0000000 16.794086 39.560715 56.902902 59.474921 61.222691 62.620783 1.2441587 diff --git a/ensemble_md/tests/data/dhdl/forced-swap/dhdl_3.xvg b/ensemble_md/tests/data/dhdl/forced-swap/dhdl_3.xvg new file mode 100644 index 0000000..8258655 --- /dev/null +++ b/ensemble_md/tests/data/dhdl/forced-swap/dhdl_3.xvg @@ -0,0 +1,238 @@ +# This file was created Sun Jan 19 05:14:48 2025 +# Created by: +# :-) GROMACS - gmx mdrun, 2022.5-dev (-: +# +# Executable: /projects/anfr8476/pkgs/gromacs-2022.5-wl/bin/gmx +# Data prefix: /projects/anfr8476/pkgs/gromacs-2022.5-wl +# Working dir: /gpfs/alpine1/scratch/anfr8476/EEXE/test_forced_swap/small_mol/forced_random/solv/rep1/sim_3/iteration_0 +# Command line: +# gmx mdrun -s sys_EE.tpr -ntomp 6 -ntmpi 1 +# gmx mdrun is part of G R O M A C S: +# +# Great Red Owns Many ACres of Sand +# +@ title "dH/d\xl\f{} and \xD\f{}H" +@ xaxis label "Time (ps)" +@ yaxis label "dH/d\xl\f{} and \xD\f{}H (kJ/mol [\xl\f{}]\S-1\N)" +@TYPE xy +@ subtitle "T = 300 (K) " +@ view 0.15, 0.15, 0.75, 0.85 +@ legend on +@ legend box on +@ legend loctype view +@ legend 0.78, 0.8 +@ legend length 2 +@ s0 legend "Thermodynamic state" +@ s1 legend "Total Energy (kJ/mol)" +@ s2 legend "dH/d\xl\f{} coul-lambda = 0.0000" +@ s3 legend "dH/d\xl\f{} vdw-lambda = 0.0000" +@ s4 legend "dH/d\xl\f{} bonded-lambda = 0.0000" +@ s5 legend "\xD\f{}H \xl\f{} to (0.0000, 0.0000, 0.0000)" +@ s6 legend "\xD\f{}H \xl\f{} to (0.1000, 0.1000, 0.1000)" +@ s7 legend "\xD\f{}H \xl\f{} to (0.3000, 0.3000, 0.3000)" +@ s8 legend "\xD\f{}H \xl\f{} to (0.6000, 0.6000, 0.6000)" +@ s9 legend "\xD\f{}H \xl\f{} to (0.7000, 0.7000, 0.7000)" +@ s10 legend "\xD\f{}H \xl\f{} to (0.8500, 0.8500, 0.8500)" +@ s11 legend "\xD\f{}H \xl\f{} to (1.0000, 1.0000, 1.0000)" +@ s12 legend "pV (kJ/mol)" +0.0000 0 -21944.324 -43.338497 2.9575920 12.263655 0.0000000 -1.9172144 0.79240708 36.090307 68.614764 187.99999 853.50322 1.2369061 +0.2000 0 -21927.299 -50.627171 -2.9984763 8.8127117 0.0000000 -3.4109315 -3.2501571 27.381995 58.083503 183.01777 1360.1046 1.2354093 +0.4000 1 -21906.078 -35.758385 -6.0012770 7.3351374 4.0875948 0.0000000 -4.1207996 2.9478942 11.008540 34.407261 93.766596 1.2377362 +0.6000 2 -21935.402 -25.686707 12.092185 6.5228958 10.694447 5.3077636 0.0000000 8.6623724 17.730399 40.581588 82.183814 1.2336378 +0.8000 1 -21978.791 -30.634449 -8.5607557 8.7350988 3.9238384 0.0000000 -2.6694752 10.160515 22.817203 62.987715 204.90989 1.2292727 +1.0000 0 -21956.004 -41.374004 -6.6583829 5.0254354 0.0000000 -3.5869296 -6.1526231 6.2493193 17.880548 50.287733 127.51790 1.2285172 +1.2000 1 -21974.684 -37.504856 4.0361347 6.2310553 3.5446637 0.0000000 -1.5903116 20.024530 42.969990 137.96340 994.10493 1.2328275 +1.4000 0 -21946.129 -57.247669 -3.3713984 8.7933693 0.0000000 -4.3014856 -7.1016194 10.530861 27.936073 84.513076 305.43465 1.2317576 +1.6000 1 -21988.178 -43.369259 8.3226967 4.8173251 3.9631330 0.0000000 -1.7109111 20.935025 42.458621 111.49471 360.57237 1.2314781 +1.8000 0 -21999.457 -59.104202 -2.0814142 5.8223295 0.0000000 -4.5872607 -7.3358217 15.684787 40.698474 140.10234 828.49865 1.2305217 +2.0000 2 -22022.734 -18.360189 16.003857 1.7999358 7.7221397 3.6075995 0.0000000 11.184913 22.867633 58.394917 165.43303 1.2318637 +2.2000 0 -22093.191 -54.240700 3.5877628 9.1439552 0.0000000 -2.5676719 3.5571351 69.211898 132.71150 399.73916 3645.2033 1.2289332 +2.4000 0 -22093.096 -32.764099 -10.795114 7.6906071 0.0000000 -2.7756524 -3.2504153 14.632806 30.133278 77.574232 373.39959 1.2312865 +2.6000 0 -22159.639 -50.969151 -8.0040646 0.93213946 0.0000000 -4.5251350 -4.8766078 34.187021 74.719269 249.30652 3576.0297 1.2320770 +2.8000 1 -22163.078 -39.043331 14.888776 9.1676674 2.5951335 0.0000000 2.1720778 39.099818 73.979568 209.64581 1426.7849 1.2284997 +3.0000 0 -22158.520 -51.877979 -7.6670713 1.0306294 0.0000000 -5.1444991 -10.900807 -4.5297026 4.1411174 30.183102 96.333406 1.2258952 +3.2000 1 -22199.059 -31.956055 15.940236 1.0291581 2.5732904 0.0000000 2.3119744 43.424255 84.345860 253.75889 2182.0961 1.2246505 +3.4000 0 -22156.863 -42.178284 2.8859770 4.1946592 0.0000000 -2.5870472 -1.0697811 34.787842 71.668429 232.14087 1986.0072 1.2265246 +3.6000 1 -22102.473 -53.644768 18.506445 1.4650311 4.8309630 0.0000000 0.10159709 45.949055 93.832261 299.44529 2968.6715 1.2259728 +3.8000 0 -22103.189 -52.863453 -2.6032610 3.3425336 0.0000000 -4.2810324 -6.9669355 10.113565 26.508928 77.659820 259.84036 1.2283367 +4.0000 1 -22055.453 -50.780144 20.891106 1.9195256 4.5706186 0.0000000 2.3306810 59.714200 117.35270 348.77445 2333.3711 1.2298274 +4.2000 0 -22060.998 -38.745567 3.2042658 5.1343608 0.0000000 -2.0886149 0.69128965 38.518320 73.444944 199.40836 873.09044 1.2296339 +4.4000 0 -22090.309 -43.749405 9.2058191 7.0789237 0.0000000 -1.6201097 3.5564677 54.182140 101.79159 294.90337 2166.9912 1.2270257 +4.6000 0 -22040.420 -42.722614 2.7985842 8.2943077 0.0000000 -2.3922990 -1.6302547 24.119015 47.279803 122.33305 390.88176 1.2236918 +4.8000 0 -21994.094 -41.697327 -0.36796159 7.5880041 0.0000000 -2.5647660 -1.6615814 25.180616 49.096650 127.71825 446.62739 1.2253435 +5.0000 0 -22002.875 -54.798012 -2.6663656 5.0651765 0.0000000 -4.2034467 -5.5783309 23.991389 56.043035 201.11678 3482.5810 1.2260804 +5.2000 1 -22045.717 -37.068512 -4.1120677 1.5001004 4.6550736 0.0000000 -4.9754647 2.3126448 11.508449 39.800591 119.52335 1.2263075 +5.4000 1 -22051.406 -41.376305 0.13687485 4.3416386 4.6199363 0.0000000 -3.4115588 11.229443 24.949816 62.651970 149.80572 1.2281423 +5.6000 0 -21962.039 -40.319931 -3.4956212 0.28323838 0.0000000 -3.5797151 -5.3632469 14.773695 34.721905 101.99352 388.63788 1.2300807 +5.8000 1 -22024.775 -39.889877 -1.2527082 1.3023208 5.0003056 0.0000000 -4.2110910 6.5914322 17.693416 50.177885 175.33981 1.2337842 +6.0000 0 -22015.316 -46.690910 -3.3213234 1.6261611 0.0000000 -3.9336316 -5.6148845 17.428857 39.744749 114.59552 447.88382 1.2362726 +6.2000 1 -21990.797 -47.542328 6.1720400 0.16736038 5.5428709 0.0000000 -2.4714173 29.931210 67.270425 258.29224 21718.181 1.2355920 +6.4000 0 -21980.576 -43.235977 -14.735087 5.0348563 0.0000000 -4.6113435 -9.6045155 -4.0324772 3.0331050 22.635668 64.796298 1.2359023 +6.6000 1 -21979.121 -59.150826 -4.9734020 1.7538012 7.2696558 0.0000000 -8.3926289 -3.7328368 4.0708851 25.618208 71.678200 1.2377797 +6.8000 3 -21894.570 17.327728 -3.2799523 1.9068737 26.695206 16.886246 4.1519318 0.0000000 2.6649138 11.054596 25.902716 1.2347668 +7.0000 4 -21914.355 21.901722 3.4802799 3.3318920 12.520134 7.0193151 -0.34728222 -2.1205821 0.0000000 6.1626092 16.627461 1.2325544 +7.2000 5 -21890.004 35.485016 -1.0851929 -0.40026894 13.952620 8.2967697 0.12514400 -4.2914742 -3.5307351 0.0000000 6.9222509 1.2382336 +7.4000 6 -21932.922 44.176682 36.099049 2.0173881 -2.4776798 -7.3390797 -14.053874 -16.341706 -14.738869 -9.5522644 0.0000000 1.2380836 +7.6000 3 -21881.648 10.639730 -2.0900533 1.1740983 15.514829 10.148338 2.6642528 0.0000000 1.6610516 7.0055171 16.624513 1.2362756 +7.8000 4 -21899.852 31.393040 11.342906 0.58967191 21.159840 12.264243 0.42544013 -3.0822315 0.0000000 9.8681363 29.582607 1.2411581 +8.0000 3 -21971.561 15.965042 8.6562605 1.9243932 20.817404 12.514575 1.6599838 0.0000000 3.8877757 15.060897 34.961770 1.2457045 +8.2000 2 -21952.762 -37.375145 1.1895251 1.8502127 23.219277 12.267773 0.0000000 1.4669928 7.9376213 25.866272 61.566861 1.2463118 +8.4000 3 -21894.908 24.376371 17.000568 0.33416110 31.706990 17.739438 1.4858955 0.0000000 5.9798094 23.066268 54.756769 1.2453170 +8.6000 2 -21881.383 -30.187853 4.9623771 0.22428890 16.841168 9.1630125 0.0000000 3.0272861 9.6611863 27.337016 59.981538 1.2455668 +8.8000 2 -21902.750 -26.630524 19.482002 1.2699745 12.120368 5.8541114 0.0000000 12.069993 25.057826 62.285198 157.26429 1.2450817 +9.0000 0 -21914.484 -55.564507 -10.372581 9.4394951 0.0000000 -4.9647834 -10.638956 -6.8201431 -1.2873431 12.940470 38.621352 1.2458252 +9.2000 1 -21915.809 -41.925499 -10.798676 8.8143139 5.2935442 0.0000000 -5.0614842 3.9521742 13.294601 37.351263 83.032277 1.2435319 +9.4000 2 -21981.758 -17.584970 -0.56114841 8.2062235 9.6800708 4.9633572 0.0000000 4.8977052 11.085350 27.916256 66.999994 1.2472523 +9.6000 1 -21911.480 -68.492088 13.534664 0.10978984 7.0175821 0.0000000 -4.2778934 26.230540 56.540629 155.41471 505.19887 1.2450323 +9.8000 1 -21827.906 -51.192123 14.954107 3.5078068 4.6327617 0.0000000 -0.48459758 33.997857 66.334720 183.88137 1150.7260 1.2508408 +10.0000 0 -21808.207 -48.139149 -4.1897192 3.9809346 0.0000000 -4.1074253 -7.4828347 5.0964263 17.716500 54.361323 145.86216 1.2530980 +10.2000 2 -21747.238 -27.701927 10.628201 5.6694460 14.347154 7.1393506 0.0000000 10.897465 24.669434 72.213012 281.73052 1.2533642 +10.4000 1 -21753.516 -58.962433 4.6409597 1.4980302 6.5156041 0.0000000 -5.1290380 18.718055 45.809763 149.62600 857.43761 1.2543386 +10.6000 1 -21741.129 -44.521492 -1.4000115 6.8231859 4.9841799 0.0000000 -3.1137227 17.722482 37.987266 100.64269 285.13303 1.2564250 +10.8000 2 -21774.064 -17.354130 13.285037 2.5969954 8.1736415 3.8621784 0.0000000 11.306331 23.566184 62.322826 189.57088 1.2566222 +11.0000 0 -21799.570 -36.555630 -3.5542488 6.3577189 0.0000000 -2.7386474 -3.7008075 14.823363 33.499039 101.79752 450.19702 1.2557217 +11.2000 0 -21816.902 -44.926060 -4.1564174 11.015846 0.0000000 -3.0604974 -4.0297055 15.929977 35.059264 99.372887 344.44219 1.2530042 +11.4000 0 -21801.035 -46.517632 -3.2360468 7.9945154 0.0000000 -3.1498058 -2.4538119 29.601642 61.345376 197.65079 2623.1984 1.2562864 +11.6000 0 -21852.717 -44.525963 -4.4795723 6.4158201 0.0000000 -3.4984294 -5.3832066 11.318725 27.284848 80.091698 312.43854 1.2568433 +11.8000 0 -21857.043 -51.334927 -4.1130342 3.9449296 0.0000000 -3.9758626 -4.2682936 24.370916 48.802650 120.98897 628.82182 1.2585080 +12.0000 1 -21869.404 -36.118774 9.0635862 0.23735148 3.5534863 0.0000000 -1.3703813 18.848560 36.926137 90.146465 260.10244 1.2585903 +12.2000 0 -21935.033 -62.247536 -1.9530368 0.17194951 0.0000000 -5.3694970 -9.3127986 10.167507 29.758659 91.312495 297.13456 1.2580688 +12.4000 1 -21940.443 -42.925247 -8.2451372 2.2170153 5.6193639 0.0000000 -6.8277361 -3.9499611 2.3221794 24.450086 260.33321 1.2574948 +12.6000 2 -21966.377 -24.288664 -6.6842866 3.2062640 15.257281 8.5936067 0.0000000 -1.2922312 1.6885057 10.065509 24.391325 1.2573129 +12.8000 5 -21968.268 52.060631 3.8657267 1.5015509 14.611023 6.7885795 -3.8625493 -8.1252608 -6.2812066 0.0000000 11.376883 1.2580211 +13.0000 4 -21966.160 20.237064 -8.4608183 1.8091617 17.071985 11.453257 3.3865387 -0.79007503 0.0000000 3.3678269 9.5639315 1.2542965 +13.2000 5 -21988.578 34.174534 15.326360 2.3430095 5.0681754 0.12545878 -6.4650144 -7.8995619 -5.8697919 0.0000000 10.067115 1.2539953 +13.4000 5 -21955.207 49.096275 -0.56719571 0.38843983 15.685753 8.1206949 -2.2089221 -6.7637514 -5.3044030 0.0000000 9.6955868 1.2541081 +13.6000 4 -21994.676 29.789818 2.3683496 3.4396110 18.960302 10.952980 0.40051608 -2.5853602 0.0000000 7.7404011 21.103880 1.2590809 +13.8000 4 -22044.631 28.566301 -1.0371375 3.2947717 18.767566 11.234149 1.1519772 -2.1855317 0.0000000 6.8260175 18.740933 1.2594895 +14.0000 3 -22061.613 16.149691 -1.4043489 1.6573504 24.333751 15.359414 3.7008377 0.0000000 2.7462878 11.904511 31.841013 1.2611247 +14.2000 4 -22123.672 27.016235 -5.4285173 2.8910737 18.709795 11.622652 2.0787260 -1.6563053 0.0000000 5.6569184 16.217857 1.2630920 +14.4000 5 -22105.361 29.642914 -3.0066605 0.68020916 11.680231 6.9787672 0.15614010 -3.5058296 -2.8709137 0.0000000 5.4505627 1.2626680 +14.6000 6 -22024.594 59.546494 0.58516854 1.1070663 6.8070996 0.70379904 -7.8282416 -12.017671 -11.069266 -7.2203638 0.0000000 1.2649424 +14.8000 6 -22027.910 60.445549 22.863033 0.41734645 -0.72200525 -6.3721617 -14.179608 -16.931969 -15.232043 -9.7859987 0.0000000 1.2631656 +15.0000 5 -22082.770 53.928162 5.4667625 1.0010427 13.529137 5.6332497 -4.9224469 -8.7075366 -6.6567248 0.0000000 12.002180 1.2672925 +15.2000 4 -22097.617 28.160034 -5.5534382 0.92149788 22.199566 14.197711 3.3010545 -1.5146664 0.0000000 5.5818570 15.921559 1.2693731 +15.4000 3 -22116.746 11.577864 3.5528529 0.95411229 17.871460 11.327851 2.4227964 0.0000000 2.5362383 10.363137 24.937403 1.2722454 +15.6000 4 -22101.174 30.339954 -9.2327585 0.56640202 23.644461 15.471179 4.0948008 -1.3371034 0.0000000 5.2394846 14.912593 1.2710314 +15.8000 6 -22060.453 45.696762 35.924995 0.078911640 -0.91600072 -5.9198205 -13.012595 -15.830678 -14.374836 -9.3912792 0.0000000 1.2715367 +16.0000 5 -22090.842 36.273636 3.1343341 -0.93418026 15.000446 8.7760855 -0.16270033 -4.8936797 -4.0030901 0.0000000 7.8572677 1.2695868 +16.2000 6 -22101.570 41.430054 10.621879 1.1134684 3.9534739 -0.72870094 -7.4567725 -10.695529 -9.7934431 -6.3397662 0.0000000 1.2665026 +16.4000 6 -22101.986 115.56961 21.759195 0.68181360 1.2112410 -8.9393846 -21.442607 -25.664555 -23.201091 -15.185056 0.0000000 1.2654340 +16.6000 3 -22115.006 26.641064 45.764969 5.3968630 26.304453 12.025506 -4.0159385 0.0000000 10.673308 42.272762 119.04656 1.2603817 +16.8000 2 -22114.777 -21.861441 29.909191 3.1581812 7.2158434 2.7442164 0.0000000 23.078316 48.864537 161.43918 1781.6297 1.2625433 +17.0000 0 -22131.693 -46.066444 4.1767106 0.38792759 0.0000000 -3.0879970 -1.7371145 34.441867 67.559556 178.94183 646.18075 1.2624425 +17.2000 0 -22113.211 -62.501480 -9.4241285 1.7504728 0.0000000 -6.2385594 -14.070724 -13.162991 -8.7184123 3.3250623 24.754231 1.2631464 +17.4000 3 -22097.609 16.244268 -11.260145 2.8058403 25.001484 16.548801 5.0244609 0.0000000 1.6431132 7.5847268 18.468700 1.2654849 +17.6000 5 -22145.908 39.081928 5.9325838 2.0483050 11.202308 5.0873081 -3.3016275 -6.6592086 -5.1457677 0.0000000 9.3224607 1.2656312 +17.8000 3 -22135.424 14.013298 -6.5820580 1.1500182 24.404982 15.942951 4.7426767 0.0000000 1.7409436 8.0100338 19.959283 1.2604877 +18.0000 5 -22208.865 50.539589 -3.6892996 0.25414133 18.359750 10.450693 -0.72434315 -6.2627971 -5.0265503 0.0000000 9.3555527 1.2615839 +18.2000 5 -22137.420 58.653126 -7.0957036 1.1623358 19.392029 10.548733 -1.6027153 -7.1996319 -5.6961810 0.0000000 10.389003 1.2594811 +18.4000 5 -22169.035 80.133072 -4.8741655 5.4163017 19.074093 7.6464424 -7.0001071 -11.840382 -8.9846828 0.0000000 15.828341 1.2565187 +18.6000 4 -22144.219 39.427422 -5.0480390 8.4001036 25.412299 14.727868 1.0792322 -3.0462601 0.0000000 9.6175793 28.087211 1.2526107 +18.8000 4 -22148.014 23.673721 10.449573 0.20339698 16.700142 10.009325 0.78606888 -2.3467939 0.0000000 8.6640621 36.794847 1.2529117 +19.0000 3 -22193.289 14.074253 21.319515 1.4440266 17.543151 9.8764662 0.026203589 0.0000000 5.4198900 23.223019 69.973673 1.2546966 +19.2000 3 -22283.445 12.043989 14.256780 0.75692093 16.021724 9.4042928 0.67650286 0.0000000 3.9213776 15.471458 37.855022 1.2559766 +19.4000 4 -22275.609 25.218731 0.83077925 1.2317039 18.462972 11.532062 1.9104692 -1.8569588 0.0000000 6.2903448 17.923902 1.2544136 +19.6000 6 -22197.018 45.333160 27.992689 0.81122136 -1.5576324 -6.3083290 -12.953542 -15.269688 -13.725333 -8.7919764 0.0000000 1.2548666 +19.8000 5 -22163.234 42.395325 12.048562 0.73196304 11.282768 4.6888187 -4.1999827 -7.5856855 -5.8790556 0.0000000 11.810698 1.2555823 +20.0000 4 -22206.199 19.197117 12.249867 0.47578040 11.039226 5.6386306 -1.2335697 -2.3826379 0.0000000 6.9116605 19.323554 1.2546961 +20.2000 5 -22227.955 35.334450 8.5588894 0.85726523 9.2021936 3.7474469 -3.6323985 -6.3685713 -4.8923887 0.0000000 8.9494700 1.2557029 +20.4000 5 -22143.598 26.041195 5.7112155 0.15801358 9.7440552 5.4954144 -0.72104819 -4.0139237 -3.2729271 0.0000000 6.7724522 1.2563497 +20.6000 6 -22155.309 59.866905 0.22481126 1.9344828 5.6021145 -0.49555938 -8.9842917 -12.820749 -11.672598 -7.4825357 0.0000000 1.2608873 +20.8000 6 -22035.832 68.119949 13.539880 0.58686173 3.0921850 -3.9344440 -13.521285 -17.243113 -15.539542 -9.9011624 0.0000000 1.2609053 +21.0000 4 -22050.096 18.529560 14.479115 0.60796916 11.875842 6.7118210 -0.43743491 -2.3610630 0.0000000 8.3065804 33.530521 1.2584534 +21.2000 2 -21981.154 -24.731823 -6.5459752 0.32183099 16.151521 9.2650097 0.0000000 -1.5761178 1.9340366 12.609828 33.692807 1.2574779 +21.4000 3 -21959.305 18.242125 -4.0265865 3.2780237 27.362502 17.201939 4.0867039 0.0000000 2.8719268 11.831420 27.852085 1.2586161 +21.6000 5 -21945.992 55.063133 2.5329003 5.8083234 12.019844 4.1781473 -6.3564195 -9.5965840 -7.1976896 0.0000000 12.090718 1.2535666 +21.8000 4 -21953.609 34.207405 38.288616 0.16972965 16.113543 6.8084139 -4.9623595 -5.4500130 0.0000000 16.359198 52.325394 1.2508649 +22.0000 3 -21946.422 20.637331 8.3173637 7.1963096 23.598010 12.975412 0.42897362 0.0000000 5.0335816 18.728072 42.559375 1.2535976 +22.2000 2 -21937.199 -40.377644 -3.2812936 3.6431208 23.740343 13.145292 0.0000000 0.80269041 8.5096339 34.163989 110.23653 1.2516413 +22.4000 3 -22011.709 13.832920 -0.76424104 2.8125730 20.828461 13.147331 2.9833683 0.0000000 2.5454133 10.382744 24.459420 1.2502075 +22.6000 5 -22010.195 50.809677 49.471024 1.0250316 2.1528335 -5.0185778 -14.351004 -15.166265 -11.244420 0.0000000 20.864272 1.2521158 +22.8000 3 -22052.793 21.357113 25.203825 2.8071299 26.523485 14.586851 -0.067835838 0.0000000 6.9645135 27.152415 68.383521 1.2568969 +23.0000 2 -22003.234 -59.586948 -5.3443346 5.9972868 39.289545 20.083046 0.0000000 -2.2274128 4.3719755 24.019312 65.721644 1.2559969 +23.2000 3 -21977.705 14.280861 2.0924950 8.7288904 15.850493 8.8773307 0.29841724 0.0000000 3.4674622 12.644245 27.758309 1.2573694 +23.4000 3 -21906.320 19.059147 13.167456 0.77755332 25.625291 15.375538 2.1095112 0.0000000 4.9720756 20.660100 55.512142 1.2565187 +23.6000 4 -21913.270 29.538338 1.4999490 0.25802255 21.564744 13.438912 2.2354241 -2.1296854 0.0000000 7.2172684 20.564250 1.2569445 +23.8000 5 -21861.602 35.531273 3.3634624 2.1820002 10.272027 4.9703895 -2.4849344 -5.6898749 -4.4383794 0.0000000 8.2696134 1.2585762 +24.0000 3 -21898.408 14.646662 -1.8723631 5.0327311 18.992699 11.583025 2.0999803 0.0000000 2.6874737 10.509263 24.224708 1.2623017 +24.2000 5 -21896.242 32.592800 16.083561 6.7917461 1.9003817 -2.5190080 -8.2309582 -8.6534778 -6.3351222 0.0000000 10.899964 1.2616057 +24.4000 4 -21895.160 19.026348 -0.76799428 2.8193822 13.783700 8.6155604 1.3605244 -1.4470813 0.0000000 4.7965851 13.407461 1.2598970 +24.6000 6 -21920.885 63.014236 19.644592 0.86474466 5.1658838 -1.2915336 -10.565152 -15.205181 -14.067294 -9.3724962 0.0000000 1.2633561 +24.8000 6 -21946.021 55.473217 10.720248 0.66350579 5.1216133 -0.81421368 -9.2295726 -13.266893 -12.169959 -7.9146228 0.0000000 1.2623836 +25.0000 5 -21974.957 44.274242 -2.6587200 0.88635647 14.590905 7.7045520 -1.5910990 -5.7819969 -4.5661235 0.0000000 8.5535999 1.2621392 +25.2000 6 -21950.625 60.882282 17.745209 0.36905420 2.7649435 -3.5314286 -12.178553 -15.772180 -14.321049 -9.2672023 0.0000000 1.2599009 +25.4000 5 -21942.393 40.299603 14.779397 2.4143412 8.0850707 2.3085881 -5.6624127 -8.2669957 -6.2950691 0.0000000 11.634610 1.2551422 +25.6000 3 -21939.334 18.299286 -1.1172724 8.4223070 22.206165 13.139229 1.7617308 0.0000000 3.7315297 14.424474 34.571121 1.2521497 +25.8000 4 -21978.338 33.316544 -3.2622025 3.8895617 21.947567 13.169157 1.5630740 -2.3797799 0.0000000 7.6670589 21.950565 1.2506225 +26.0000 5 -21962.148 41.668331 2.4340696 1.6818213 11.576731 5.5431584 -2.8795643 -6.4129661 -4.9820898 0.0000000 9.1088923 1.2476197 +26.2000 4 -21868.404 20.859760 9.5340099 1.6577319 11.616668 6.3514042 -0.79945182 -2.3551378 0.0000000 7.0824132 20.524812 1.2499681 +26.4000 3 -21778.617 11.100700 28.107929 0.57080376 11.249108 5.3809051 -1.9719452 0.0000000 5.4987057 21.888699 63.567479 1.2533339 +26.6000 1 -21777.533 -35.110832 -11.488214 0.35984150 5.1247127 0.0000000 -7.2125086 -9.8159996 -8.1258853 -2.5300392 7.9890953 1.2516078 +26.8000 4 -21793.051 24.218132 -3.7923348 2.2424695 18.653290 11.976988 2.6108074 -1.4838772 0.0000000 5.3505945 15.409197 1.2522929 +27.0000 3 -21860.781 12.967634 10.804914 2.7944126 15.966138 9.3481436 0.68255866 0.0000000 3.8617438 15.418607 39.055173 1.2528764 +27.2000 2 -21870.973 -28.185486 19.294853 5.1612449 13.988100 6.4373962 0.0000000 16.478838 34.923238 98.480229 1151.1076 1.2504106 +27.4000 1 -21880.021 -37.331841 11.878849 7.4477987 2.9597506 0.0000000 2.1053248 47.223345 95.563909 329.37749 6981.8225 1.2516719 +27.6000 0 -21871.457 -72.135529 0.83176923 5.3778477 0.0000000 -5.1652500 -6.1560113 29.047877 60.571550 154.50565 406.13436 1.2511175 +27.8000 0 -21821.238 -63.815918 -30.543547 11.109639 0.0000000 -5.6337415 -1.6276115 72.515226 147.32570 450.64063 356621.03 1.2481166 +28.0000 0 -21793.990 -50.773811 2.5037992 9.1750183 0.0000000 -2.8298113 -0.88462321 37.941310 76.437760 245.97954 4387.7270 1.2482851 +28.2000 0 -21853.746 -46.969543 7.0231090 7.2874212 0.0000000 -2.2325199 0.48825421 35.809646 65.859814 160.57429 508.46124 1.2477696 +28.4000 0 -21871.031 -36.065514 1.6147296 8.6189518 0.0000000 -1.5992506 2.3416449 41.867196 76.401777 192.22800 662.77019 1.2449166 +28.6000 1 -21879.939 -40.863747 -10.071182 4.9893823 5.2384044 0.0000000 -6.5814344 -5.4320998 -1.1209798 11.442785 38.252115 1.2492996 +28.8000 2 -21847.160 -21.447262 11.024570 1.1520289 10.957793 5.5809445 0.0000000 8.2322152 17.927760 45.052683 104.85518 1.2524501 +29.0000 1 -21789.146 -41.603584 -9.7131186 5.4480829 5.2739525 0.0000000 -6.3723144 -3.7582569 1.7205773 17.943952 57.352181 1.2533976 +29.2000 0 -21773.391 -37.219753 -9.5818005 8.2720232 0.0000000 -3.2815258 -6.2735991 -0.093674578 5.7742805 19.871097 43.531886 1.2563679 +29.4000 1 -21817.258 -28.103483 3.0282042 8.6588955 2.4490343 0.0000000 0.44995002 26.063333 53.124792 181.34159 3207.1478 1.2569453 +29.6000 0 -21750.664 -41.384346 3.3394482 9.1355181 0.0000000 -2.0795007 -0.50878293 25.795750 47.374951 108.78208 263.65622 1.2522900 +29.8000 1 -21748.814 -30.417240 -5.2053480 5.4962592 3.5860799 0.0000000 -3.5960795 2.1277670 8.2862588 24.084916 53.392786 1.2467350 +30.0000 0 -21864.164 -83.775612 4.7120972 7.6317563 0.0000000 -5.5585279 -6.6858681 31.357798 68.197729 199.10574 825.84872 1.2439259 +30.2000 1 -21830.598 -54.518559 1.3967420 8.4255219 5.5995600 0.0000000 -4.2671990 12.067199 28.358882 80.126721 279.12178 1.2466609 +30.4000 0 -21865.629 -86.819420 8.0865154 9.8462553 0.0000000 -5.0775250 -3.0751158 55.654898 114.77696 368.18774 7009.2192 1.2467629 +30.6000 1 -21867.109 -63.138233 8.3822870 11.729662 5.7686861 0.0000000 -2.5104520 26.404692 53.937680 147.16631 1994.3815 1.2464453 +30.8000 1 -21840.203 -58.377182 22.915379 8.5945148 4.6966675 0.0000000 3.9205422 73.354593 143.06041 438.87617 3783.1191 1.2450638 +31.0000 0 -21836.543 -69.889091 0.017291129 2.4479134 0.0000000 -5.5298099 -8.4870357 19.488434 48.185578 160.14190 1293.9686 1.2452877 +31.2000 1 -21990.447 -77.997253 20.061396 8.7903509 6.7460432 0.0000000 -1.9271279 40.933806 83.609936 252.87110 2761.8204 1.2458274 +31.4000 0 -21974.508 -72.592056 3.6725512 6.6296968 0.0000000 -4.9573481 -6.3393465 27.126122 59.309800 169.11461 667.95678 1.2492301 +31.6000 2 -21961.621 -26.925186 32.625591 3.3417530 9.6951611 3.8492427 0.0000000 22.849112 47.224635 136.73847 606.84795 1.2465994 +31.8000 1 -21978.115 -60.559685 7.0374408 0.13047147 6.6974070 0.0000000 -5.1387314 15.027879 35.924229 105.80593 427.00337 1.2449785 +32.0000 2 -21936.723 -19.330631 24.432581 0.69119990 7.0932798 2.9474742 0.0000000 15.402761 30.268624 74.988691 212.21562 1.2443680 +32.2000 0 -21892.023 -48.315475 -2.1201000 1.7074840 0.0000000 -3.6388224 -2.4994597 36.090032 70.984104 181.73108 533.93986 1.2428902 +32.4000 1 -21926.004 -69.335373 5.3591628 1.0264916 7.9301980 0.0000000 -5.8937517 23.838314 60.389347 240.31935 7517.0174 1.2424828 +32.6000 2 -21981.977 -18.215565 16.484028 7.1440210 5.8796369 2.3771675 0.0000000 12.243721 23.061350 51.055246 107.78357 1.2472175 +32.8000 1 -21979.584 -42.000408 3.3915086 3.6017497 4.3700536 0.0000000 -3.1934783 11.643211 25.804115 66.205647 165.73752 1.2479181 +33.0000 2 -22017.219 -22.695503 -4.6228757 1.4161190 14.275922 8.0670286 0.0000000 -0.84567538 2.3140801 11.139328 26.410578 1.2461213 +33.2000 4 -22065.723 27.931042 1.3973634 8.5627480 14.688402 7.7817708 -1.1898447 -2.8403174 0.0000000 8.1006193 22.228830 1.2480443 +33.4000 5 -22160.598 39.616856 29.708416 0.99082071 3.8774417 -1.9139990 -9.5654533 -10.709160 -7.9257826 0.0000000 13.894952 1.2466638 +33.6000 3 -22162.850 13.980423 13.355594 2.6221437 16.653367 9.2445562 0.023906980 0.0000000 4.1485570 15.341094 34.473395 1.2454400 +33.8000 2 -22146.199 -27.852276 14.323059 2.6225243 14.061259 7.0084105 0.0000000 10.015352 21.291902 51.399325 112.16304 1.2448322 +34.0000 1 -22072.469 -35.445724 -4.1826930 6.5241203 3.9549190 0.0000000 -3.8797972 2.7333339 9.5765717 26.731930 57.454294 1.2425225 +34.2000 0 -22031.475 -50.204124 -8.5319729 8.9145374 0.0000000 -4.1902770 -7.6917397 4.3690097 17.839681 66.830272 319.11855 1.2441996 +34.4000 1 -22000.117 -42.970192 -8.0624084 6.3972640 5.1898994 0.0000000 -5.9403648 -1.8496418 4.2287769 20.340169 50.554482 1.2450097 +34.6000 0 -22040.340 -45.388039 -10.389755 0.55460787 0.0000000 -4.6132113 -7.8822690 12.652130 37.386197 158.94764 3277.2466 1.2459781 +34.8000 1 -22076.617 -34.879288 6.6402822 4.4004326 3.2922079 0.0000000 -0.56785055 24.050902 48.327342 145.51661 1185.0780 1.2465352 +35.0000 0 -22014.766 -53.154316 -3.5881658 7.0886173 0.0000000 -4.1628370 -7.2208319 9.2491417 28.403895 114.98695 1254.5789 1.2507077 +35.2000 0 -21906.758 -80.823502 -8.8612642 1.1127642 0.0000000 -7.7702965 -17.283260 -16.447283 -11.344230 2.7079682 28.749777 1.2526543 +35.4000 2 -21892.178 -29.307768 -2.1332095 8.7433128 15.228085 8.2679921 0.0000000 2.2707289 7.7824038 23.018889 59.632145 1.2462796 +35.6000 1 -21845.686 -29.224909 5.1444516 2.7135811 2.8653404 0.0000000 -0.84266322 19.054878 39.006619 115.73956 684.11747 1.2501708 +35.8000 0 -21803.031 -71.172623 0.077710271 1.2666876 0.0000000 -5.7682113 -9.8085269 9.2917674 27.434349 80.794308 265.27930 1.2540058 +36.0000 1 -21800.367 -30.600681 -6.9443460 4.0521536 3.9936437 0.0000000 -4.0242804 2.8706335 11.200432 37.798958 123.12600 1.2515309 +36.2000 0 -21825.709 -26.062082 -1.9265573 0.95929611 0.0000000 -2.1036288 -1.9800929 17.447680 34.789012 86.483650 223.23977 1.2523506 +36.4000 0 -21870.131 -65.543236 -10.179163 1.7231570 0.0000000 -6.1238639 -12.808933 -9.5106164 -3.4643372 14.534138 67.409227 1.2539344 +36.6000 3 -21855.412 15.205326 8.7067738 5.5651097 17.866745 9.9092194 0.22170620 0.0000000 4.0898400 15.120179 34.008450 1.2560135 +36.8000 2 -21870.010 -25.636562 48.412579 2.9135363 5.7955803 1.2423785 0.0000000 33.820940 69.390996 216.43881 1518.8133 1.2542375 +37.0000 1 -21772.061 -49.890038 -2.4179029 0.10851029 6.1351810 0.0000000 -6.7617408 1.6034165 14.191683 62.353880 314.38143 1.2563856 +37.2000 0 -21827.781 -53.981449 -5.5677691 2.0474875 0.0000000 -4.8040174 -8.1062984 12.275547 34.565968 125.49207 1032.9154 1.2519917 +37.4000 1 -21789.367 -38.590721 -9.8855639 0.52847409 5.4006326 0.0000000 -7.0906462 -7.1119065 -3.5151388 6.6735862 25.363816 1.2512425 +37.6000 3 -21737.291 9.4562874 6.7480464 1.0326600 13.737624 8.4685962 1.3245503 0.0000000 2.5773635 10.171761 23.898382 1.2520005 +37.8000 4 -21669.506 20.223783 -4.8343191 5.4714918 12.938835 7.9033328 0.96416798 -1.4692623 0.0000000 4.6264264 12.651081 1.2521288 +38.0000 6 -21601.133 57.362335 6.7386813 0.68992031 7.2772713 0.97704010 -8.0537335 -12.700614 -11.741553 -7.6740696 0.0000000 1.2520666 +38.2000 4 -21708.410 22.003983 30.077187 1.0235604 8.6374704 2.8592926 -4.5780712 -4.0819582 0.0000000 11.401113 32.687166 1.2486092 +38.4000 3 -21688.703 19.627750 12.591658 0.31133509 26.236267 15.624955 2.1216954 0.0000000 4.8528357 19.979034 59.074318 1.2469311 +38.6000 3 -21703.365 19.232702 0.58847606 9.4736414 23.334377 13.217519 1.2024267 0.0000000 4.1477090 15.517947 35.053402 1.2486875 +38.8000 4 -21785.955 28.679409 7.3418531 1.3506662 17.981277 10.373171 0.13201094 -2.7115504 0.0000000 8.1929082 22.704357 1.2478460 +39.0000 4 -21766.578 24.696751 9.4046907 8.3398838 10.460389 4.4884635 -3.0398489 -3.2665102 0.0000000 8.9640715 25.013117 1.2482303 +39.2000 4 -21763.445 16.242535 -8.9392366 0.80375636 15.105017 10.490253 3.6890434 -0.36200088 0.0000000 2.2691651 6.7861445 1.2512314 +39.4000 6 -21734.457 54.607525 1.5196505 1.0491375 6.7074071 1.2318085 -6.5420395 -10.674909 -9.9449733 -6.5978720 0.0000000 1.2533427 +39.6000 6 -21803.078 68.373940 7.0824919 3.7850811 3.0518581 -3.2101297 -11.899762 -15.561233 -14.145496 -9.1836575 0.0000000 1.2522539 +39.8000 6 -21822.492 73.619293 3.6315372 2.5494051 6.5356759 -0.81135422 -10.981742 -15.695559 -14.378847 -9.3617561 0.0000000 1.2536534 +40.0000 4 -21829.297 40.265335 -0.42265129 0.77138031 27.154670 16.413176 2.0569118 -2.8656206 0.0000000 8.9714997 24.397801 1.2565694 diff --git a/ensemble_md/tests/test_replica_exchange_EE.py b/ensemble_md/tests/test_replica_exchange_EE.py index c2af9b8..7cc9ed3 100644 --- a/ensemble_md/tests/test_replica_exchange_EE.py +++ b/ensemble_md/tests/test_replica_exchange_EE.py @@ -839,6 +839,22 @@ def test_accept_or_reject(self, params_dict): assert swap_bool_2 is False assert swap_bool_3 is True + def test_deter_swap_index(self, params_dict): + REXEE = get_REXEE_instance(params_dict) + REXEE.n_tot = 28 + REXEE.s = 7 + REXEE.template['nstdhdl'] = 100 + REXEE.template['nstxout'] = 1000 + REXEE.template['n_sim'] = 4 + + dhdl_files = [ + os.path.join(input_path, f"dhdl/forced-swap/dhdl_{i}.xvg") for i in range(REXEE.n_sim) + ] + swap_index, swap_state = REXEE._deter_swap_index([0, 1], dhdl_files, [[6, 7], [13, 14], [20, 21]]) + assert swap_index[0] in [14, 15, 16] + assert swap_index[1] in [10, 16, 19] + assert swap_state == [6, 7] + def test_weight_correction(self, params_dict): REXEE = get_REXEE_instance(params_dict) From 618346f4972e90965b66a448ba05ba2ad3d3068a Mon Sep 17 00:00:00 2001 From: Anika Date: Fri, 31 Jan 2025 06:53:46 -0700 Subject: [PATCH 15/32] update analysis --- ensemble_md/analysis/analyze_traj.py | 26 +++ ensemble_md/cli/analyze_REXEE.py | 240 +++++++++++++++++---------- 2 files changed, 182 insertions(+), 84 deletions(-) diff --git a/ensemble_md/analysis/analyze_traj.py b/ensemble_md/analysis/analyze_traj.py index 8285862..7c13381 100644 --- a/ensemble_md/analysis/analyze_traj.py +++ b/ensemble_md/analysis/analyze_traj.py @@ -685,6 +685,8 @@ def plot_transit_time(trajs, N, fig_prefix=None, dt=None, folder='.'): units : str The units of the time. """ + import pandas as pd + if dt is None: x = np.arange(len(trajs[0])) units = 'step' @@ -824,6 +826,14 @@ def plot_transit_time(trajs, N, fig_prefix=None, dt=None, folder='.'): plt.savefig(f'{folder}/hist_{fig_names[t]}', dpi=600) else: plt.savefig(f'{folder}/{fig_prefix}_hist_{fig_names[t]}', dpi=600) + #Save to csv + sim_list, rt_list = [], [] + for n in range(len(t_roundtrip_list)): + for rt in t_roundtrip_list[n]: + sim_list.append(n) + rt_list.append(rt) + df_rt = pd.DataFrame({'Sim': sim_list, 'Round Trip Time': rt_list}) + df_rt.to_csv(f'{folder}/roundtrip_times.csv') return t_0k_list, t_k0_list, t_roundtrip_list, units @@ -1416,3 +1426,19 @@ def end_states_only_traj(working_dir, n_sim, n_iter, l0_states, l1_states, swap_ traj_add = md.load(f'{working_dir}/sim_{rep}/iteration_{iteration}/traj.trr', top=f'{working_dir}/sim_{rep}/iteration_0/{name}.gro') traj = md.join(traj, traj_add) traj.save_xtc(f'{working_dir}/analysis/{state}_{rep}.xtc') + +def concat_sim_traj(working_dir, n_sim, n_iter): + import mdtraj as md + import os + + for rep in range(n_sim): + if os.path.exists(f'{working_dir}/sim_{rep}/iteration_0/confout_backup.gro'): + name = 'confout_backup' + else: + name = 'confout' + + traj = md.load(f'{working_dir}/sim_{rep}/iteration_0/traj.trr', top=f'{working_dir}/sim_{rep}/iteration_0/{name}.gro') + for iteration in range(1, n_iter): + traj_add = md.load(f'{working_dir}/sim_{rep}/iteration_{iteration}/traj.trr', top=f'{working_dir}/sim_{rep}/iteration_0/{name}.gro') + traj = md.join([traj, traj_add]) + traj.save_xtc(f'{working_dir}/analysis/sim{rep}_concat.xtc') diff --git a/ensemble_md/cli/analyze_REXEE.py b/ensemble_md/cli/analyze_REXEE.py index 37e0df3..5f08d28 100644 --- a/ensemble_md/cli/analyze_REXEE.py +++ b/ensemble_md/cli/analyze_REXEE.py @@ -180,36 +180,37 @@ def main(): ) rmse = analyze_traj.calc_hist_rmse(hist_data, REXEE.state_ranges) print(f'The RMSE of accumulated histogram counts of the state index: {rmse:.0f}') - - # 2-4. Stitch the time series of state index for different replicas - if os.path.isfile(args.state_trajs_for_sim) is True: - print('\n2-4. Reading in the stitched time series of state index for different replicas ...') - state_trajs_for_sim = np.load(args.state_trajs_for_sim) - else: - # This may take a while. - print('2-4. Stitching time series of state index for each replica ...') - shifts = list(REXEE.s * np.arange(REXEE.n_sim)) - dhdl_files = [natsort.natsorted(glob.glob(f'sim_{i}/iteration_*/*dhdl*xvg')) for i in range(REXEE.n_sim)] - state_trajs_for_sim = analyze_traj.stitch_time_series_for_sim(dhdl_files, shifts) - - # 2-5. Plot the time series of state index for different state sets - print('\n2-5. Plotting the time series of state index for different state sets ...') - analyze_traj.plot_state_trajs( - state_trajs_for_sim, - REXEE.state_ranges, - f'{args.dir}/state_trajs_for_sim.png', - title_prefix='State set' - ) - - # 2-6. Plot the histograms of state index for different state sets - print('\n2-6. Plotting the histograms of state index for different state sets') - analyze_traj.plot_state_hist( - state_trajs_for_sim, - REXEE.state_ranges, - f'{args.dir}/state_hist_for_sim.png', - prefix='State set', - subplots=True - ) + + if REXEE.proposal != 'forced_random' and REXEE.proposal != 'forced_swap': # Need to FIX THIS FOR FORCED-RANDOM + # 2-4. Stitch the time series of state index for different replicas + if os.path.isfile(args.state_trajs_for_sim) is True: + print('\n2-4. Reading in the stitched time series of state index for different replicas ...') + state_trajs_for_sim = np.load(args.state_trajs_for_sim) + else: + # This may take a while. + print('2-4. Stitching time series of state index for each replica ...') + shifts = list(REXEE.s * np.arange(REXEE.n_sim)) + dhdl_files = [natsort.natsorted(glob.glob(f'sim_{i}/iteration_*/*dhdl*xvg')) for i in range(REXEE.n_sim)] + state_trajs_for_sim = analyze_traj.stitch_time_series_for_sim(dhdl_files, shifts) + + # 2-5. Plot the time series of state index for different state sets + print('\n2-5. Plotting the time series of state index for different state sets ...') + analyze_traj.plot_state_trajs( + state_trajs_for_sim, + REXEE.state_ranges, + f'{args.dir}/state_trajs_for_sim.png', + title_prefix='State set' + ) + + # 2-6. Plot the histograms of state index for different state sets + print('\n2-6. Plotting the histograms of state index for different state sets') + analyze_traj.plot_state_hist( + state_trajs_for_sim, + REXEE.state_ranges, + f'{args.dir}/state_hist_for_sim.png', + prefix='State set', + subplots=True + ) # 2-7. Plot the overall state transition matrices calculated from the state-space trajectories print('\n2-7. Plotting the overall state transition matrices from different trajectories ...') @@ -390,61 +391,36 @@ def main(): if REXEE.free_energy is True: section_idx += 1 print(f'\n[ Section {section_idx}. Free energy calculations ]') - - # 4-1. Subsampling the data - data_list = [] # either a list of u_nk or a list of dhdl - if REXEE.df_data_type == 'u_nk': - if os.path.isfile(f'{args.dir}/u_nk_data.pickle') is True: - print('Loading the preprocessed data u_nk ...') - with open(f'{args.dir}/u_nk_data.pickle', 'rb') as handle: - data_all = pickle.load(handle) - data_list, t_idx_list, g_list = data_all[0], data_all[1], data_all[2] - else: # should always be 'dhdl' - if os.path.isfile(f'{args.dir}/dHdl_data.pickle') is True: - print('Loading the preprocessed data dHdl ...') - with open(f'{args.dir}/dHdl_data.pickle', 'rb') as handle: - data_all = pickle.load(handle) - data_list, t_idx_list, g_list = data_all[0], data_all[1], data_all[2] - - if data_list == []: - files_list = [natsort.natsorted(glob.glob(f'sim_{i}/iteration_*/*dhdl*xvg')) for i in range(REXEE.n_sim)] - data_list, t_idx_list, g_list = analyze_free_energy.preprocess_data(files_list, REXEE.temp, REXEE.df_data_type, REXEE.df_spacing) # noqa: E501 - - data_all = [data_list, t_idx_list, g_list] - with open(f'{args.dir}/{REXEE.df_data_type}_data.pickle', 'wb') as handle: - pickle.dump(data_all, handle, protocol=pickle.HIGHEST_PROTOCOL) - - # 4-2. Calculate the free energy profile - f, f_err, estimators = analyze_free_energy.calculate_free_energy(data_list, REXEE.state_ranges, REXEE.df_method, REXEE.err_method, REXEE.n_bootstrap, REXEE.seed) # noqa: E501 - - print('Plotting the full-range free energy profile ...') - analyze_free_energy.plot_free_energy(f, f_err, f'{args.dir}/free_energy_profile.png') - - print('The full-range free energy profile averaged over all replicas:') - print(f" {', '.join(f'{f[i]:.3f} +/- {f_err[i]:.3f} kT' for i in range(REXEE.n_tot))}") - print(f'The free energy difference between the coupled and decoupled states: {f[-1]:.3f} +/- {f_err[-1]:.3f} kT') # noqa: E501 - - if REXEE.df_ref is not None: - rmse_list = analyze_free_energy.calculate_df_rmse(estimators, REXEE.df_ref, REXEE.state_ranges) - for i in range(REXEE.n_sim): - print(f'RMSE of the free energy profile for alchemical range {i} (states {REXEE.state_ranges[i][0]} to {REXEE.state_ranges[i][-1]}): {rmse_list[i]:.2f} kT') # noqa: E501 - - # 4-3. Recalculate the free energy profile if subsampling_avg is True - if REXEE.subsampling_avg is True: - print('\nUsing averaged start index of the equilibrated data and the avearged statistic inefficiency to re-perform free energy calculations ...') # noqa: E501 - t_avg = int(np.mean(t_idx_list)) + 1 # Using the ceiling function to be a little more conservative - g_avg = np.array(g_list).prod() ** (1/len(g_list)) # geometric mean - print(f'Averaged start index: {t_avg}') - print(f'Averaged statistical inefficiency: {g_avg:.2f}') - - data_list, t_idx_list, g_list = analyze_free_energy.preprocess_data(files_list, REXEE.temp, REXEE.df_data_type, REXEE.df_spacing, t_avg, g_avg) # noqa: E501 - data_all = [data_list, t_idx_list, g_list] - with open(f'{args.dir}/{REXEE.df_data_type}_data_avg_subsampling.pickle', 'wb') as handle: - pickle.dump(data_all, handle, protocol=pickle.HIGHEST_PROTOCOL) - + + if REXEE.modify_coords == False: + # 4-1. Subsampling the data + data_list = [] # either a list of u_nk or a list of dhdl + if REXEE.df_data_type == 'u_nk': + if os.path.isfile(f'{args.dir}/u_nk_data.pickle') is True: + print('Loading the preprocessed data u_nk ...') + with open(f'{args.dir}/u_nk_data.pickle', 'rb') as handle: + data_all = pickle.load(handle) + data_list, t_idx_list, g_list = data_all[0], data_all[1], data_all[2] + else: # should always be 'dhdl' + if os.path.isfile(f'{args.dir}/dHdl_data.pickle') is True: + print('Loading the preprocessed data dHdl ...') + with open(f'{args.dir}/dHdl_data.pickle', 'rb') as handle: + data_all = pickle.load(handle) + data_list, t_idx_list, g_list = data_all[0], data_all[1], data_all[2] + + if data_list == []: + files_list = [natsort.natsorted(glob.glob(f'sim_{i}/iteration_*/*dhdl*xvg')) for i in range(REXEE.n_sim)] + data_list, t_idx_list, g_list = analyze_free_energy.preprocess_data(files_list, REXEE.temp, REXEE.df_data_type, REXEE.df_spacing) # noqa: E501 + + data_all = [data_list, t_idx_list, g_list] + with open(f'{args.dir}/{REXEE.df_data_type}_data.pickle', 'wb') as handle: + pickle.dump(data_all, handle, protocol=pickle.HIGHEST_PROTOCOL) + + # 4-2. Calculate the free energy profile f, f_err, estimators = analyze_free_energy.calculate_free_energy(data_list, REXEE.state_ranges, REXEE.df_method, REXEE.err_method, REXEE.n_bootstrap, REXEE.seed) # noqa: E501 + print('Plotting the full-range free energy profile ...') - analyze_free_energy.plot_free_energy(f, f_err, f'{args.dir}/free_energy_profile_avg_subsampling.png') + analyze_free_energy.plot_free_energy(f, f_err, f'{args.dir}/free_energy_profile.png') print('The full-range free energy profile averaged over all replicas:') print(f" {', '.join(f'{f[i]:.3f} +/- {f_err[i]:.3f} kT' for i in range(REXEE.n_tot))}") @@ -455,9 +431,103 @@ def main(): for i in range(REXEE.n_sim): print(f'RMSE of the free energy profile for alchemical range {i} (states {REXEE.state_ranges[i][0]} to {REXEE.state_ranges[i][-1]}): {rmse_list[i]:.2f} kT') # noqa: E501 + # 4-3. Recalculate the free energy profile if subsampling_avg is True + if REXEE.subsampling_avg is True: + print('\nUsing averaged start index of the equilibrated data and the avearged statistic inefficiency to re-perform free energy calculations ...') # noqa: E501 + t_avg = int(np.mean(t_idx_list)) + 1 # Using the ceiling function to be a little more conservative + g_avg = np.array(g_list).prod() ** (1/len(g_list)) # geometric mean + print(f'Averaged start index: {t_avg}') + print(f'Averaged statistical inefficiency: {g_avg:.2f}') + + data_list, t_idx_list, g_list = analyze_free_energy.preprocess_data(files_list, REXEE.temp, REXEE.df_data_type, REXEE.df_spacing, t_avg, g_avg) # noqa: E501 + data_all = [data_list, t_idx_list, g_list] + with open(f'{args.dir}/{REXEE.df_data_type}_data_avg_subsampling.pickle', 'wb') as handle: + pickle.dump(data_all, handle, protocol=pickle.HIGHEST_PROTOCOL) + + f, f_err, estimators = analyze_free_energy.calculate_free_energy(data_list, REXEE.state_ranges, REXEE.df_method, REXEE.err_method, REXEE.n_bootstrap, REXEE.seed) # noqa: E501 + print('Plotting the full-range free energy profile ...') + analyze_free_energy.plot_free_energy(f, f_err, f'{args.dir}/free_energy_profile_avg_subsampling.png') + + print('The full-range free energy profile averaged over all replicas:') + print(f" {', '.join(f'{f[i]:.3f} +/- {f_err[i]:.3f} kT' for i in range(REXEE.n_tot))}") + print(f'The free energy difference between the coupled and decoupled states: {f[-1]:.3f} +/- {f_err[-1]:.3f} kT') # noqa: E501 + + if REXEE.df_ref is not None: + rmse_list = analyze_free_energy.calculate_df_rmse(estimators, REXEE.df_ref, REXEE.state_ranges) + for i in range(REXEE.n_sim): + print(f'RMSE of the free energy profile for alchemical range {i} (states {REXEE.state_ranges[i][0]} to {REXEE.state_ranges[i][-1]}): {rmse_list[i]:.2f} kT') # noqa: E501 + + else: # MT-REXEE means each simulation is a seperate transformation + for sim in range(REXEE.n_sim): + print(f'Computing Free Energy for Simulation {sim}') + # 4-1. Subsampling the data + data_list = [] # either a list of u_nk or a list of dhdl + if REXEE.df_data_type == 'u_nk': + if os.path.isfile(f'{args.dir}/u_nk_data_{sim}.pickle') is True: + print('Loading the preprocessed data u_nk ...') + with open(f'{args.dir}/u_nk_data_{sim}.pickle', 'rb') as handle: + data_all = pickle.load(handle) + data_list, t_idx_list, g_list = data_all[0], data_all[1], data_all[2] + else: # should always be 'dhdl' + if os.path.isfile(f'{args.dir}/dHdl_data_{sim}.pickle') is True: + print('Loading the preprocessed data dHdl ...') + with open(f'{args.dir}/dHdl_data_{sim}.pickle', 'rb') as handle: + data_all = pickle.load(handle) + data_list, t_idx_list, g_list = data_all[0], data_all[1], data_all[2] + + if data_list == []: + files_list = [natsort.natsorted(glob.glob(f'sim_{sim}/iteration_*/*dhdl*xvg'))] + data_list, t_idx_list, g_list = analyze_free_energy.preprocess_data(files_list, REXEE.temp, REXEE.df_data_type, REXEE.df_spacing) # noqa: E501 + + data_all = [data_list, t_idx_list, g_list] + with open(f'{args.dir}/{REXEE.df_data_type}_data_{sim}.pickle', 'wb') as handle: + pickle.dump(data_all, handle, protocol=pickle.HIGHEST_PROTOCOL) + + # 4-2. Calculate the free energy profile + f, f_err, estimators = analyze_free_energy.calculate_free_energy(data_list, REXEE.state_ranges[sim], REXEE.df_method, REXEE.err_method, REXEE.n_bootstrap, REXEE.seed) # noqa: E501 + + print('Plotting the full-range free energy profile ...') + analyze_free_energy.plot_free_energy(f, f_err, f'{args.dir}/free_energy_profile_{sim}.png') + + print('The full-range free energy profile averaged over all replicas:') + print(f" {', '.join(f'{f[i]:.3f} +/- {f_err[i]:.3f} kT' for i in range(REXEE.n_tot))}") + print(f'The free energy difference between the coupled and decoupled states: {f[-1]:.3f} +/- {f_err[-1]:.3f} kT') # noqa: E501 + + if REXEE.df_ref is not None: + rmse_list = analyze_free_energy.calculate_df_rmse(estimators, REXEE.df_ref, REXEE.state_ranges[sim]) + for i in range(REXEE.n_sim): + print(f'RMSE of the free energy profile for alchemical range {i} (states {REXEE.state_ranges[i][0]} to {REXEE.state_ranges[i][-1]}): {rmse_list[i]:.2f} kT') # noqa: E501 + + # 4-3. Recalculate the free energy profile if subsampling_avg is True + if REXEE.subsampling_avg is True: + print('\nUsing averaged start index of the equilibrated data and the avearged statistic inefficiency to re-perform free energy calculations ...') # noqa: E501 + t_avg = int(np.mean(t_idx_list)) + 1 # Using the ceiling function to be a little more conservative + g_avg = np.array(g_list).prod() ** (1/len(g_list)) # geometric mean + print(f'Averaged start index: {t_avg}') + print(f'Averaged statistical inefficiency: {g_avg:.2f}') + + data_list, t_idx_list, g_list = analyze_free_energy.preprocess_data(files_list, REXEE.temp, REXEE.df_data_type, REXEE.df_spacing, t_avg, g_avg) # noqa: E501 + data_all = [data_list, t_idx_list, g_list] + with open(f'{args.dir}/{REXEE.df_data_type}_data_avg_subsampling_{sim}.pickle', 'wb') as handle: + pickle.dump(data_all, handle, protocol=pickle.HIGHEST_PROTOCOL) + + f, f_err, estimators = analyze_free_energy.calculate_free_energy(data_list, REXEE.state_ranges[sim], REXEE.df_method, REXEE.err_method, REXEE.n_bootstrap, REXEE.seed) # noqa: E501 + print('Plotting the full-range free energy profile ...') + analyze_free_energy.plot_free_energy(f, f_err, f'{args.dir}/free_energy_profile_avg_subsampling_{sim}.png') + + print('The full-range free energy profile averaged over all replicas:') + print(f" {', '.join(f'{f[i]:.3f} +/- {f_err[i]:.3f} kT' for i in range(REXEE.n_tot))}") + print(f'The free energy difference between the coupled and decoupled states: {f[-1]:.3f} +/- {f_err[-1]:.3f} kT') # noqa: E501 + + if REXEE.df_ref is not None: + rmse_list = analyze_free_energy.calculate_df_rmse(estimators, REXEE.df_ref, REXEE.state_ranges[sim]) + for i in range(REXEE.n_sim): + print(f'RMSE of the free energy profile for alchemical range {i} (states {REXEE.state_ranges[i][0]} to {REXEE.state_ranges[i][-1]}): {rmse_list[i]:.2f} kT') # noqa: E501 + # Section 5. Process trajecotries for MT-REXEE if REXEE.modify_coords is not None: # Section 5.1. Create end-state trajecotries for each simulation + print('5.1. Create end-state trajecotries for each simulation') l0, l1, ps_per_frame = gmx_parser.get_end_states(f'{REXEE.working_dir}/sim_0/iteration_0/expanded.mdp') n_sim, n_iter = np.shape(rep_trajs) if REXEE.swap_rep_pattern is None: @@ -465,8 +535,10 @@ def main(): analyze_traj.end_states_only_traj(REXEE.working_dir, n_sim, n_iter, l0, l1, REXEE.swap_rep_pattern, ps_per_frame) # Section 5.2. Create concatenated trajectories for each individual simulation + print('5.2. Create concatenated trajectories for each individual simulation') + analyze_traj.concat_sim_traj(REXEE.working_dir, n_sim, n_iter) - # Section 4. Calculate the time spent in GROMACS (This could take a while.) + # Section 6. Calculate the time spent in GROMACS (This could take a while.) t_wall_tot, t_sync, _ = utils.analyze_REXEE_time() print(f'\nTotal wall time GROMACS spent to finish all iterations: {utils.format_time(t_wall_tot)}') print(f'Total time spent in syncrhonizing all replicas: {utils.format_time(t_sync)}') From a7cb9a33c807caab80efe6ba9d289ff103c3f5db Mon Sep 17 00:00:00 2001 From: Anika Date: Thu, 6 Mar 2025 10:44:17 -0700 Subject: [PATCH 16/32] update cli commands --- ensemble_md/cli/analyze_REXEE.py | 1 + ensemble_md/cli/run_REXEE.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ensemble_md/cli/analyze_REXEE.py b/ensemble_md/cli/analyze_REXEE.py index 29f74bc..3737f35 100644 --- a/ensemble_md/cli/analyze_REXEE.py +++ b/ensemble_md/cli/analyze_REXEE.py @@ -121,6 +121,7 @@ def main(): print('\nData analysis of the simulation ensemble') print('========================================') + # Section 1. Analysis based on transitions between state sets print('[ Section 1. Analysis based on transitions between state sets/replicas ]') section_idx += 1 diff --git a/ensemble_md/cli/run_REXEE.py b/ensemble_md/cli/run_REXEE.py index 0abebda..61fb5b4 100644 --- a/ensemble_md/cli/run_REXEE.py +++ b/ensemble_md/cli/run_REXEE.py @@ -138,6 +138,7 @@ def main(): REXEE.g_vecs = [list(i) for i in np.load(args.g_vecs)] if REXEE.fixed_weights is not True and os.path.isfile(args.equil) is True: REXEE.equil = np.load(args.equil) + print(f'equil: {REXEE.equil}') else: start_idx = None @@ -305,7 +306,7 @@ def main(): try: if rank == 0: for j in range(len(swap_list)): - if not os.path.exists(f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout_backup.gro') and not os.path.exists(f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout_backup.gro'): # noqa: E501 + if not os.path.exists(f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout_backup.gro') or not os.path.exists(f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout_backup.gro'): # noqa: E501 print('\nModifying the coordinates of the following output GRO files ...') # gro_1 and gro_2 are the simlation outputs (that we want to back up) and the inputs to modify_coords # noqa: E501 gro_1 = f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout.gro' From fca1f0a0fd18638be04f884cbb54aa31cedc39cf Mon Sep 17 00:00:00 2001 From: Anika Date: Thu, 6 Mar 2025 10:45:07 -0700 Subject: [PATCH 17/32] update utils --- ensemble_md/utils/coordinate_swap.py | 4 ++-- ensemble_md/utils/gmx_parser.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ensemble_md/utils/coordinate_swap.py b/ensemble_md/utils/coordinate_swap.py index e8d0a7c..95afbbd 100644 --- a/ensemble_md/utils/coordinate_swap.py +++ b/ensemble_md/utils/coordinate_swap.py @@ -442,7 +442,7 @@ def get_miss_coord(mol_align, mol_ref, name_align, name_ref, df_atom_swap, dir, for a in range(mol_align_select.n_atoms): if a != conn0_align: mol_align_select.xyz[0, a, :] = _rotate_point_around_axis(mol_align_select.xyz[0, a, :], mol_ref_select.xyz[0, conn0_ref, :], axis_rot, theta_min) # noqa: E501 - + # Add coordinates to df for r in range(len(df_atom_swap.index)): if df_atom_swap.iloc[r]['Direction'] == 'miss' and df_atom_swap.iloc[r]['Swap'] == dir: @@ -1184,7 +1184,7 @@ def get_names(input, resname): continue while '' in line_sep: line_sep.remove('') - if line_sep[0] == '\n': + if line_sep[0] == '\n' or line == '[ bonds ]\n': start_line = l+2 break if line_sep[3] == resname: diff --git a/ensemble_md/utils/gmx_parser.py b/ensemble_md/utils/gmx_parser.py index a279e71..13068ec 100644 --- a/ensemble_md/utils/gmx_parser.py +++ b/ensemble_md/utils/gmx_parser.py @@ -438,7 +438,7 @@ def deter_atom_order(mol_file, resname): split_line.remove('') if resname in split_line[0]: if len(split_line[1]) > 5: - split_line = coordinate_swap.sep_merge(split_line) + split_line = coordinate_swap._sep_merge(split_line) atom_order.append(split_line[1]) elif len(atom_order) != 0: break From 01f1a6d5271ad6bfe2edf91a0785cd3c3af1e9c7 Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Thu, 6 Mar 2025 11:05:30 -0700 Subject: [PATCH 18/32] Remove forced_swap option and rename forced_random to random_range --- ensemble_md/replica_exchange_EE.py | 45 ++++++++---------------------- 1 file changed, 12 insertions(+), 33 deletions(-) diff --git a/ensemble_md/replica_exchange_EE.py b/ensemble_md/replica_exchange_EE.py index a72da0d..7d09fd5 100644 --- a/ensemble_md/replica_exchange_EE.py +++ b/ensemble_md/replica_exchange_EE.py @@ -196,8 +196,8 @@ def set_params(self, analysis): self.warnings.append(f'Warning: Parameter "{i}" specified in the input YAML file is not recognizable.') # Step 4: Check if the parameters in the YAML file are well-defined - if self.proposal not in [None, 'single', 'neighboring', 'exhaustive', 'forced_swap', 'forced_random']: # deprecated option: multiple # noqa: E501 - raise ParameterError("The specified proposal scheme is not available. Available options include 'single', 'neighboring', 'exhaustive', 'forced_swap', 'forced_random'.") # noqa: E501 + if self.proposal not in [None, 'single', 'neighboring', 'exhaustive', 'random_range']: # deprecated option: multiple # noqa: E501 + raise ParameterError("The specified proposal scheme is not available. Available options include 'single', 'neighboring', 'exhaustive', 'random_range'.") # noqa: E501 if self.df_method not in [None, 'TI', 'BAR', 'MBAR']: raise ParameterError("The specified free energy estimator is not available. Available options include 'TI', 'BAR', and 'MBAR'.") # noqa: E501 @@ -809,7 +809,7 @@ def identify_swappable_pairs(self, states, state_ranges, dhdl_files, iteration=N swappable pairs after an attempted swap is accepted. iteration : int The iteration number will determine which direction the swaps will be performed. This option is - only necessary when using the "forced_swap" proposal scheme. + only necessary when using the "random_range" proposal scheme. Returns ------- @@ -834,22 +834,7 @@ def identify_swappable_pairs(self, states, state_ranges, dhdl_files, iteration=N n_sim = len(states) sim_idx = list(range(n_sim)) states_for_swap = [] - if self.proposal == 'forced_swap': - potential_swappables = [] - if iteration % 2 == 0: # Swap up for self.n_sim - 1 swaps - for n in np.arange(0, n_sim-2, 2): - potential_swappables.append([n, n+1]) - else: # and then swap down for self.n_sim - 1 swaps and repeat - for n in np.arange(1, n_sim-1, 2): - potential_swappables.append([n, n+1]) - swappables, swap_index = [], [] - for swap in potential_swappables: - index, state = self._deter_swap_index(swap, dhdl_files, self.add_swappables) - if len(index) == 2: - swap_index.append(index) - swappables.append(swap) - states_for_swap.append(state) - elif self.proposal == 'forced_random': + if self.proposal == 'random_range': potential_swappables = [] for n in np.arange(0, n_sim-1, 1): potential_swappables.append([n, n+1]) @@ -934,7 +919,7 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): This list can be generated :obj:`.extract_final_dhdl_info`. iteration : int The iteration number will determine which direction the swaps will be performed. This option is only - necessary when using the "forced_swap" proposal scheme. + necessary when using the "random_range" proposal scheme. Returns ------- @@ -944,10 +929,7 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): A list of tuples showing the accepted swaps. """ swap_list = [] - if self.proposal == 'forced_swap': - n_ex = int(np.floor(self.n_sim / 2)) # This is the maximum, not necessarily the number that will always be reached. # noqa - swap_index = [] - elif self.proposal == 'forced_random': + if self.proposal == 'random_range': swap_index = [] n_ex = int(np.floor(self.n_sim / 2)) # This is the maximum, not necessarily the number that will always be reached. # noqa n_ex_FR = 0 @@ -983,13 +965,13 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): swap_index_accept = [] for i in range(n_ex): # Update the list of swappable pairs starting from the 2nd attempted swap for the exhaustive swap method. - if (self.proposal == 'exhaustive' or self.proposal == 'forced_swap' or self.proposal == 'forced_random') and i >= 1: # noqa: E501 + if (self.proposal == 'exhaustive' or self.proposal == 'random_range') and i >= 1: # noqa: E501 # Note that this should be done regardless of the acceptance/rejection of the previously drawn pairs. # Also note that at this point, swap is still the last attempted swap. swappables = [i for i in swappables if set(i).intersection(set(swap)) == set()] # noqa: F821 print(f'\nRemaining swappable pairs: {swappables}') - if len(swappables) == 0 and (self.proposal == 'exhaustive' or self.proposal == 'forced_swap' or self.proposal == 'forced_random'): # noqa: E501 + if len(swappables) == 0 and (self.proposal == 'exhaustive' or self.proposal == 'random_range'): # noqa: E501 # This should only happen when the method of exhaustive swaps is used. if i == 0: self.n_empty_swappable += 1 @@ -998,13 +980,10 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): else: if self.proposal == 'exhaustive': n_ex_exhaustive += 1 - if self.proposal == 'forced_random': + if self.proposal == 'random_range': n_ex_FR += 1 - if self.proposal == 'forced_swap': - swap = swappables[0] - else: - swap = ReplicaExchangeEE.propose_swap(swappables) + swap = ReplicaExchangeEE.propose_swap(swappables) print(f'\nProposed swap: {swap}') if swap == []: # the same as len(swappables) == 0, self.proposal must not be exhaustive if this line is reached. # noqa: E501 @@ -1013,7 +992,7 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): break # no need to re-identify swappable pairs and draw new samples else: self.n_swap_attempts += 1 - if self.verbose is True and self.proposal != 'exhaustive' and self.proposal != 'forced_swap' and self.proposal != 'forced_random': # noqa: E501 + if self.verbose is True and self.proposal != 'exhaustive' and self.proposal != 'random_range': # noqa: E501 print(f'A swap ({i + 1}/{n_ex}) is proposed between the configurations of Simulation {swap[0]} (state {states[swap[0]]}) and Simulation {swap[1]} (state {states[swap[1]]}) ...') # noqa: E501 if self.modify_coords_fn is not None: @@ -1035,7 +1014,7 @@ def get_swapping_pattern(self, dhdl_files, states, iteration=None): if swap_bool is True: swap_list.append(swap) - if self.proposal == "forced_swap" or self.proposal == "forced_random": + if self.proposal == "random_range": for p, p_swap in enumerate(all_swappables): if p_swap == swap: break From 373906407cfab4b49733f72483f9c4ed9be21b50 Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Thu, 6 Mar 2025 11:15:54 -0700 Subject: [PATCH 19/32] Fix linting --- ensemble_md/analysis/analyze_traj.py | 47 ++++++++++++++++++++++++++-- ensemble_md/cli/analyze_REXEE.py | 19 ++++++----- ensemble_md/utils/coordinate_swap.py | 2 +- 3 files changed, 54 insertions(+), 14 deletions(-) diff --git a/ensemble_md/analysis/analyze_traj.py b/ensemble_md/analysis/analyze_traj.py index bbde168..1dd6a34 100644 --- a/ensemble_md/analysis/analyze_traj.py +++ b/ensemble_md/analysis/analyze_traj.py @@ -833,7 +833,7 @@ def plot_transit_time(trajs, N, fig_prefix=None, dt=None, folder='.'): plt.savefig(f'{folder}/hist_{fig_names[t]}', dpi=600) else: plt.savefig(f'{folder}/{fig_prefix}_hist_{fig_names[t]}', dpi=600) - #Save to csv + # Save to csv sim_list, rt_list = [], [] for n in range(len(t_roundtrip_list)): for rt in t_roundtrip_list[n]: @@ -1350,6 +1350,30 @@ def get_delta_w_updates(log_file, plot=False): def end_states_only_traj(working_dir, n_sim, n_iter, l0_states, l1_states, swap_rep_pattern, ps_per_frame): + """ + Create a trajectory which is a concatenation off all frames for each unique end state. + + Parameters + ---------- + working_dir : str + path for the current working directory + n_sim : int + the number of simulations run + n_iter : int + the number of iterations run + l0_states : list of int + the lambda states which correspond to lambda=0 + l1_states : list of int + the lambda states which correspond to lambda=1 + swap_rep_pattern : list of int + the replica swapping pattern which will indicate which end states are common + ps_per_frame : float + the timestep to convert the time in the GROMACS dh/dl file to frames in the trajecotry + + Returns + ------- + None + """ import pandas as pd import os import mdtraj as md @@ -1434,7 +1458,24 @@ def end_states_only_traj(working_dir, n_sim, n_iter, l0_states, l1_states, swap_ traj = md.join(traj, traj_add) traj.save_xtc(f'{working_dir}/analysis/{state}_{rep}.xtc') + def concat_sim_traj(working_dir, n_sim, n_iter): + """ + Create a trajectory which is a concatenation off each iterations trajectory + + Parameters + ---------- + working_dir : str + path for the current working directory + n_sim : int + the number of simulations run + n_iter : int + the number of iterations run + + Returns + ------- + None + """ import mdtraj as md import os @@ -1444,8 +1485,8 @@ def concat_sim_traj(working_dir, n_sim, n_iter): else: name = 'confout' - traj = md.load(f'{working_dir}/sim_{rep}/iteration_0/traj.trr', top=f'{working_dir}/sim_{rep}/iteration_0/{name}.gro') + traj = md.load(f'{working_dir}/sim_{rep}/iteration_0/traj.trr', top=f'{working_dir}/sim_{rep}/iteration_0/{name}.gro') # noqa: E501 for iteration in range(1, n_iter): - traj_add = md.load(f'{working_dir}/sim_{rep}/iteration_{iteration}/traj.trr', top=f'{working_dir}/sim_{rep}/iteration_0/{name}.gro') + traj_add = md.load(f'{working_dir}/sim_{rep}/iteration_{iteration}/traj.trr', top=f'{working_dir}/sim_{rep}/iteration_0/{name}.gro') # noqa: E501 traj = md.join([traj, traj_add]) traj.save_xtc(f'{working_dir}/analysis/sim{rep}_concat.xtc') diff --git a/ensemble_md/cli/analyze_REXEE.py b/ensemble_md/cli/analyze_REXEE.py index 3737f35..18116b0 100644 --- a/ensemble_md/cli/analyze_REXEE.py +++ b/ensemble_md/cli/analyze_REXEE.py @@ -121,7 +121,6 @@ def main(): print('\nData analysis of the simulation ensemble') print('========================================') - # Section 1. Analysis based on transitions between state sets print('[ Section 1. Analysis based on transitions between state sets/replicas ]') section_idx += 1 @@ -182,9 +181,9 @@ def main(): ) rmse = analyze_traj.calc_hist_rmse(hist_data, REXEE.state_ranges) print(f'The RMSE of accumulated histogram counts of the state index: {rmse:.0f}') - + if REXEE.proposal != 'forced_random' and REXEE.proposal != 'forced_swap': # Need to FIX THIS FOR FORCED-RANDOM - # 2-4. Stitch the time series of state index for different replicas + # 2-4. Stitch the time series of state index for different replicas if os.path.isfile(args.state_trajs_for_sim) is True: print('\n2-4. Reading in the stitched time series of state index for different replicas ...') state_trajs_for_sim = np.load(args.state_trajs_for_sim) @@ -393,8 +392,8 @@ def main(): if REXEE.free_energy is True: section_idx += 1 print(f'\n[ Section {section_idx}. Free energy calculations ]') - - if REXEE.modify_coords == False: + + if REXEE.modify_coords is False: # 4-1. Subsampling the data data_list = [] # either a list of u_nk or a list of dhdl if REXEE.df_data_type == 'u_nk': @@ -411,7 +410,7 @@ def main(): data_list, t_idx_list, g_list = data_all[0], data_all[1], data_all[2] if data_list == []: - files_list = [natsort.natsorted(glob.glob(f'sim_{i}/iteration_*/*dhdl*xvg')) for i in range(REXEE.n_sim)] + files_list = [natsort.natsorted(glob.glob(f'sim_{i}/iteration_*/*dhdl*xvg')) for i in range(REXEE.n_sim)] # noqa: E501 data_list, t_idx_list, g_list = analyze_free_energy.preprocess_data(files_list, REXEE.temp, REXEE.df_data_type, REXEE.df_spacing) # noqa: E501 data_all = [data_list, t_idx_list, g_list] @@ -496,14 +495,14 @@ def main(): print(f'The free energy difference between the coupled and decoupled states: {f[-1]:.3f} +/- {f_err[-1]:.3f} kT') # noqa: E501 if REXEE.df_ref is not None: - rmse_list = analyze_free_energy.calculate_df_rmse(estimators, REXEE.df_ref, REXEE.state_ranges[sim]) + rmse_list = analyze_free_energy.calculate_df_rmse(estimators, REXEE.df_ref, REXEE.state_ranges[sim]) # noqa: E501 for i in range(REXEE.n_sim): print(f'RMSE of the free energy profile for alchemical range {i} (states {REXEE.state_ranges[i][0]} to {REXEE.state_ranges[i][-1]}): {rmse_list[i]:.2f} kT') # noqa: E501 # 4-3. Recalculate the free energy profile if subsampling_avg is True if REXEE.subsampling_avg is True: print('\nUsing averaged start index of the equilibrated data and the avearged statistic inefficiency to re-perform free energy calculations ...') # noqa: E501 - t_avg = int(np.mean(t_idx_list)) + 1 # Using the ceiling function to be a little more conservative + t_avg = int(np.mean(t_idx_list)) + 1 # Using the ceiling function to be a little more conservative # noqa: E501 g_avg = np.array(g_list).prod() ** (1/len(g_list)) # geometric mean print(f'Averaged start index: {t_avg}') print(f'Averaged statistical inefficiency: {g_avg:.2f}') @@ -515,14 +514,14 @@ def main(): f, f_err, estimators = analyze_free_energy.calculate_free_energy(data_list, REXEE.state_ranges[sim], REXEE.df_method, REXEE.err_method, REXEE.n_bootstrap, REXEE.seed) # noqa: E501 print('Plotting the full-range free energy profile ...') - analyze_free_energy.plot_free_energy(f, f_err, f'{args.dir}/free_energy_profile_avg_subsampling_{sim}.png') + analyze_free_energy.plot_free_energy(f, f_err, f'{args.dir}/free_energy_profile_avg_subsampling_{sim}.png') # noqa: E501 print('The full-range free energy profile averaged over all replicas:') print(f" {', '.join(f'{f[i]:.3f} +/- {f_err[i]:.3f} kT' for i in range(REXEE.n_tot))}") print(f'The free energy difference between the coupled and decoupled states: {f[-1]:.3f} +/- {f_err[-1]:.3f} kT') # noqa: E501 if REXEE.df_ref is not None: - rmse_list = analyze_free_energy.calculate_df_rmse(estimators, REXEE.df_ref, REXEE.state_ranges[sim]) + rmse_list = analyze_free_energy.calculate_df_rmse(estimators, REXEE.df_ref, REXEE.state_ranges[sim]) # noqa: E501 for i in range(REXEE.n_sim): print(f'RMSE of the free energy profile for alchemical range {i} (states {REXEE.state_ranges[i][0]} to {REXEE.state_ranges[i][-1]}): {rmse_list[i]:.2f} kT') # noqa: E501 diff --git a/ensemble_md/utils/coordinate_swap.py b/ensemble_md/utils/coordinate_swap.py index 84702b2..8451027 100644 --- a/ensemble_md/utils/coordinate_swap.py +++ b/ensemble_md/utils/coordinate_swap.py @@ -361,7 +361,7 @@ def get_miss_coord(mol_align, mol_ref, name_align, name_ref, df_atom_swap, dir, for a in range(mol_align_select.n_atoms): if a != conn0_align: mol_align_select.xyz[0, a, :] = _rotate_point_around_axis(mol_align_select.xyz[0, a, :], mol_ref_select.xyz[0, conn0_ref, :], axis_rot, theta_min) # noqa: E501 - + # Add coordinates to df for r in range(len(df_atom_swap.index)): if df_atom_swap.iloc[r]['Swap'] == dir: From a9fb24c1359feb775934351dabf07c9d0223cc9b Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Thu, 6 Mar 2025 11:59:49 -0700 Subject: [PATCH 20/32] Fix test errors --- ensemble_md/analysis/analyze_traj.py | 1 + ensemble_md/tests/test_analyze_traj.py | 2 +- ensemble_md/tests/test_replica_exchange_EE.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ensemble_md/analysis/analyze_traj.py b/ensemble_md/analysis/analyze_traj.py index 1dd6a34..cb917f6 100644 --- a/ensemble_md/analysis/analyze_traj.py +++ b/ensemble_md/analysis/analyze_traj.py @@ -543,6 +543,7 @@ def plot_state_hist(trajs, state_ranges, fig_name, stack=True, figsize=None, pre dir_list = [] for i in fig_name.split('/')[:-1]: dir_list.append(i) + dir_list.append('/') dir_path = ''.join(dir_list) np.save(f'{dir_path}/hist_data.npy', hist_data) else: diff --git a/ensemble_md/tests/test_analyze_traj.py b/ensemble_md/tests/test_analyze_traj.py index b47b3fd..66a7959 100644 --- a/ensemble_md/tests/test_analyze_traj.py +++ b/ensemble_md/tests/test_analyze_traj.py @@ -595,7 +595,7 @@ def test_plot_state_hist(mock_plt): } # Clean up - os.remove('hist_data.npy') + os.remove('ensemble_md/tests/data/hist_data.npy') def test_calc_hist_rmse(): diff --git a/ensemble_md/tests/test_replica_exchange_EE.py b/ensemble_md/tests/test_replica_exchange_EE.py index a5cd32b..b4a5549 100644 --- a/ensemble_md/tests/test_replica_exchange_EE.py +++ b/ensemble_md/tests/test_replica_exchange_EE.py @@ -90,7 +90,7 @@ def test_set_params_error(self, params_dict): params_dict['n_sim'] = 4 # so params_dict can be read without failing in the assertions below # 2. Available options - check_param_error(params_dict, 'proposal', "The specified proposal scheme is not available. Available options include 'single', 'neighboring', 'exhaustive', 'forced_swap', 'forced_random'.", 'cool', 'exhaustive') # noqa: E501 + check_param_error(params_dict, 'proposal', "The specified proposal scheme is not available. Available options include 'single', 'neighboring', 'exhaustive', 'random_range'.", 'cool', 'exhaustive') # noqa: E501 check_param_error(params_dict, 'df_method', "The specified free energy estimator is not available. Available options include 'TI', 'BAR', and 'MBAR'.") # noqa: E501 check_param_error(params_dict, 'err_method', "The specified method for error estimation is not available. Available options include 'propagate', and 'bootstrap'.") # noqa: E501 From bc33e22421dbd8c8abdb2bead6a3f4fb918e453c Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Thu, 6 Mar 2025 12:08:54 -0700 Subject: [PATCH 21/32] Remove redundancy --- ensemble_md/cli/run_REXEE.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/ensemble_md/cli/run_REXEE.py b/ensemble_md/cli/run_REXEE.py index d155262..bfdf43b 100644 --- a/ensemble_md/cli/run_REXEE.py +++ b/ensemble_md/cli/run_REXEE.py @@ -306,12 +306,11 @@ def main(): try: if rank == 0: for j in range(len(swap_list)): - if not os.path.exists(f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout_backup.gro') or not os.path.exists(f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout_backup.gro'): # noqa: E501 - print('\nModifying the coordinates of the following output GRO files ...') - # gro_1 and gro_2 are the simlation outputs (that we want to back up) and the inputs to modify_coords # noqa: E501 - gro_1 = f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout.gro' - gro_2 = f'{REXEE.working_dir}/sim_{swap_list[j][1]}/iteration_{i-1}/confout.gro' - print(f' - {gro_1}\n - {gro_2}') + print('\nModifying the coordinates of the following output GRO files ...') + # gro_1 and gro_2 are the simlation outputs (that we want to back up) and the inputs to modify_coords # noqa: E501 + gro_1 = f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout.gro' + gro_2 = f'{REXEE.working_dir}/sim_{swap_list[j][1]}/iteration_{i-1}/confout.gro' + print(f' - {gro_1}\n - {gro_2}') # Check that swap was not performed before checkpoint was created if os.path.exists(gro_1.split('.gro')[0] + '_backup.gro') and os.path.exists(gro_2.split('.gro')[0] + '_backup.gro'): # noqa: E501 From ff7171510b9742b486be3e6e8fa6ef976cae8aa9 Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Thu, 6 Mar 2025 13:21:01 -0700 Subject: [PATCH 22/32] Add checkpoint file for tracking the frame selected for the swap --- ensemble_md/cli/run_REXEE.py | 14 ++++++++++++++ ensemble_md/replica_exchange_EE.py | 3 +++ 2 files changed, 17 insertions(+) diff --git a/ensemble_md/cli/run_REXEE.py b/ensemble_md/cli/run_REXEE.py index bfdf43b..8540ded 100644 --- a/ensemble_md/cli/run_REXEE.py +++ b/ensemble_md/cli/run_REXEE.py @@ -139,6 +139,8 @@ def main(): if REXEE.fixed_weights is not True and os.path.isfile(args.equil) is True: REXEE.equil = np.load(args.equil) print(f'equil: {REXEE.equil}') + if REXEE.proposal == 'random_range' and os.path.isfile('track_swap_frame.npy'): + REXEE.track_swap_frame = np.load('track_swap_frame.npy') else: start_idx = None @@ -268,6 +270,16 @@ def main(): # In run_REXEE(i, swap_pattern), where the tpr files will be generated, we use the top file at the # level of the simulation (the file that will be shared by all simulations). For the gro file, we # pass swap_pattern to the function to figure it out internally. + + if REXEE.proposal == 'random_range': + # 3-5. Keep track of the frames used for swapping in each trajectory + track_frame = np.full(REXEE.n_sim, -1) + for s in range(len(swap_list)): + swap = swap_list[s] + track_frame[swap[0]] = swap_index[s][0] + track_frame[swap[1]] = swap_index[s][1] + REXEE.track_swap_frame.append(track_frame) + print(track_frame) else: swap_pattern, swap_list = None, None @@ -343,6 +355,8 @@ def main(): np.save(args.ckpt, REXEE.rep_trajs) if REXEE.fixed_weights is not True: np.save(args.equil, REXEE.equil) + if REXEE.proposal == 'random_range': + np.save('track_swap_frame.npy', REXEE.track_swap_frame) # Save the npy files at the end of the simulation anyway. if rank == 0: diff --git a/ensemble_md/replica_exchange_EE.py b/ensemble_md/replica_exchange_EE.py index 7d09fd5..3751d01 100644 --- a/ensemble_md/replica_exchange_EE.py +++ b/ensemble_md/replica_exchange_EE.py @@ -471,6 +471,9 @@ def set_params(self, analysis): else: self.modify_coords_fn = None + # 7-13. A list of the frames actually utilized for the swaps in each iteration. + self.track_swap_frame = [] + # Step 8. Check the executables if analysis is False: self.check_gmx_executable() From 40ce7ff6aa1cdac037cf77443204524cdeecf0f4 Mon Sep 17 00:00:00 2001 From: Anika Date: Thu, 6 Mar 2025 13:34:56 -0700 Subject: [PATCH 23/32] Add file closure --- ensemble_md/replica_exchange_EE.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ensemble_md/replica_exchange_EE.py b/ensemble_md/replica_exchange_EE.py index 7d09fd5..da490a3 100644 --- a/ensemble_md/replica_exchange_EE.py +++ b/ensemble_md/replica_exchange_EE.py @@ -1675,6 +1675,7 @@ def default_coords_fn(self, molA_file_name, molB_file_name, swap_index): # Print box size molB_new.write(molA_file[-1]) + molB_new.close() # Print new coordinates to file # Reprint preamble text @@ -1692,6 +1693,7 @@ def default_coords_fn(self, molA_file_name, molB_file_name, swap_index): # Print box size molA_new.write(molB_file[-1]) + molA_new.close() # Rename temp files os.rename('A_hybrid_swap.gro', molB_dir + '/confout.gro') From 471f8847c88295898ef1ee2e4ccad5663886ed62 Mon Sep 17 00:00:00 2001 From: Anika Date: Fri, 7 Mar 2025 14:55:43 -0700 Subject: [PATCH 24/32] Fix checkpoint error --- ensemble_md/cli/run_REXEE.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ensemble_md/cli/run_REXEE.py b/ensemble_md/cli/run_REXEE.py index 8540ded..44556c1 100644 --- a/ensemble_md/cli/run_REXEE.py +++ b/ensemble_md/cli/run_REXEE.py @@ -140,7 +140,7 @@ def main(): REXEE.equil = np.load(args.equil) print(f'equil: {REXEE.equil}') if REXEE.proposal == 'random_range' and os.path.isfile('track_swap_frame.npy'): - REXEE.track_swap_frame = np.load('track_swap_frame.npy') + REXEE.track_swap_frame = list(np.load('track_swap_frame.npy')) else: start_idx = None From 0a68dafa410a829c3a1290661dc567149009bdbe Mon Sep 17 00:00:00 2001 From: Anika Date: Fri, 7 Mar 2025 14:56:27 -0700 Subject: [PATCH 25/32] Fix MTREXEE FE issue --- ensemble_md/analysis/analyze_free_energy.py | 9 +++++++-- ensemble_md/cli/analyze_REXEE.py | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ensemble_md/analysis/analyze_free_energy.py b/ensemble_md/analysis/analyze_free_energy.py index 0d2d1a0..34f8237 100644 --- a/ensemble_md/analysis/analyze_free_energy.py +++ b/ensemble_md/analysis/analyze_free_energy.py @@ -247,7 +247,7 @@ def _combine_df_adjacent(df_adjacent, state_ranges, df_err_adjacent=None, err_ty return df, df_err, overlap_bool -def calculate_free_energy(data, state_ranges, df_method="MBAR", err_method="propagate", n_bootstrap=None, seed=None): +def calculate_free_energy(data, state_ranges, df_method="MBAR", err_method="propagate", n_bootstrap=None, seed=None, MTREXEE=False): """ Caculates the averaged free energy profile with the chosen method given :math:`u_{nk}` or :math:`dH/dλ` data obtained from all replicas of the REXEE simulation. Available methods include TI, BAR, and MBAR. TI @@ -275,6 +275,8 @@ def calculate_free_energy(data, state_ranges, df_method="MBAR", err_method="prop seed : int, Optional The random seed for bootstrapping. Only relevant when :code:`err_method` is :code:`"bootstrap"`. The default is :code:`None`. + MTREXEE : bool + Whether this is a MT-REXEE simulation or not Returns ------- @@ -299,7 +301,10 @@ def calculate_free_energy(data, state_ranges, df_method="MBAR", err_method="prop >>> f, _, _ = analyze_free_energy.calculate_free_energy(data_list, state_ranges, "MBAR", "propagate") """ n_sim = len(data) - n_tot = state_ranges[-1][-1] + 1 + if MTREXEE is False: + n_tot = state_ranges[-1][-1] + 1 + else: + n_tot = state_ranges[-1] + 1 estimators = _apply_estimators(data, df_method) df_adjacent, df_err_adjacent = _calculate_df_adjacent(estimators) df, df_err, overlap_bool = _combine_df_adjacent(df_adjacent, state_ranges, df_err_adjacent, err_type='propagate') diff --git a/ensemble_md/cli/analyze_REXEE.py b/ensemble_md/cli/analyze_REXEE.py index 18116b0..5a7e8e6 100644 --- a/ensemble_md/cli/analyze_REXEE.py +++ b/ensemble_md/cli/analyze_REXEE.py @@ -182,7 +182,7 @@ def main(): rmse = analyze_traj.calc_hist_rmse(hist_data, REXEE.state_ranges) print(f'The RMSE of accumulated histogram counts of the state index: {rmse:.0f}') - if REXEE.proposal != 'forced_random' and REXEE.proposal != 'forced_swap': # Need to FIX THIS FOR FORCED-RANDOM + if REXEE.proposal != 'random_range': # Need to FIX THIS FOR RANDOM-Range # 2-4. Stitch the time series of state index for different replicas if os.path.isfile(args.state_trajs_for_sim) is True: print('\n2-4. Reading in the stitched time series of state index for different replicas ...') @@ -485,7 +485,7 @@ def main(): pickle.dump(data_all, handle, protocol=pickle.HIGHEST_PROTOCOL) # 4-2. Calculate the free energy profile - f, f_err, estimators = analyze_free_energy.calculate_free_energy(data_list, REXEE.state_ranges[sim], REXEE.df_method, REXEE.err_method, REXEE.n_bootstrap, REXEE.seed) # noqa: E501 + f, f_err, estimators = analyze_free_energy.calculate_free_energy(data_list, REXEE.state_ranges[sim], REXEE.df_method, REXEE.err_method, REXEE.n_bootstrap, REXEE.seed, MTREXEE=True) # noqa: E501 print('Plotting the full-range free energy profile ...') analyze_free_energy.plot_free_energy(f, f_err, f'{args.dir}/free_energy_profile_{sim}.png') From 8903a7dd1c723801a52c123e3dec7093e9075ec0 Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Fri, 7 Mar 2025 15:10:32 -0700 Subject: [PATCH 26/32] Fix issue with swaps on checkpoints --- ensemble_md/cli/run_REXEE.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/ensemble_md/cli/run_REXEE.py b/ensemble_md/cli/run_REXEE.py index 44556c1..f5b300d 100644 --- a/ensemble_md/cli/run_REXEE.py +++ b/ensemble_md/cli/run_REXEE.py @@ -279,7 +279,6 @@ def main(): track_frame[swap[0]] = swap_index[s][0] track_frame[swap[1]] = swap_index[s][1] REXEE.track_swap_frame.append(track_frame) - print(track_frame) else: swap_pattern, swap_list = None, None @@ -317,6 +316,13 @@ def main(): if REXEE.modify_coords_fn is not None: try: if rank == 0: + # If previous swaps were performed undo them + for j in range(REXEE.n_sim): + gro_backup = f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout_backup.gro' + gro = f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout.gro' + if os.path.exists(gro_backup): + os.rename(gro_backup, gro) + for j in range(len(swap_list)): print('\nModifying the coordinates of the following output GRO files ...') # gro_1 and gro_2 are the simlation outputs (that we want to back up) and the inputs to modify_coords # noqa: E501 @@ -324,18 +330,14 @@ def main(): gro_2 = f'{REXEE.working_dir}/sim_{swap_list[j][1]}/iteration_{i-1}/confout.gro' print(f' - {gro_1}\n - {gro_2}') - # Check that swap was not performed before checkpoint was created - if os.path.exists(gro_1.split('.gro')[0] + '_backup.gro') and os.path.exists(gro_2.split('.gro')[0] + '_backup.gro'): # noqa: E501 - print('\nSwap already performed') - else: - # Now we rename gro_1 and gro_2 to back them up - gro_1_backup = gro_1.split('.gro')[0] + '_backup.gro' - gro_2_backup = gro_2.split('.gro')[0] + '_backup.gro' - os.rename(gro_1, gro_1_backup) - os.rename(gro_2, gro_2_backup) - - # Here we input gro_1_backup and gro_2_backup and modify_coords_fn will save the modified gro files as gro_1 and gro_2 # noqa: E501 - REXEE.modify_coords_fn(gro_1_backup, gro_2_backup, swap_index[j]) # the order should not matter # noqa: E501 + # Now we rename gro_1 and gro_2 to back them up + gro_1_backup = gro_1.split('.gro')[0] + '_backup.gro' + gro_2_backup = gro_2.split('.gro')[0] + '_backup.gro' + os.rename(gro_1, gro_1_backup) + os.rename(gro_2, gro_2_backup) + + # Here we input gro_1_backup and gro_2_backup and modify_coords_fn will save the modified gro files as gro_1 and gro_2 # noqa: E501 + REXEE.modify_coords_fn(gro_1_backup, gro_2_backup, swap_index[j]) # the order should not matter # noqa: E501 except Exception: print('\n--------------------------------------------------------------------------\n') print(f'\nAn error occurred on rank 0:\n{traceback.format_exc()}') From f4f833eae3ee0404e217a01277bad238add52ea2 Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Fri, 7 Mar 2025 15:15:14 -0700 Subject: [PATCH 27/32] Fix FE function for MTREXEE --- ensemble_md/analysis/analyze_free_energy.py | 9 +++++---- ensemble_md/tests/test_analyze_free_energy.py | 7 ++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/ensemble_md/analysis/analyze_free_energy.py b/ensemble_md/analysis/analyze_free_energy.py index 34f8237..4ca609b 100644 --- a/ensemble_md/analysis/analyze_free_energy.py +++ b/ensemble_md/analysis/analyze_free_energy.py @@ -178,7 +178,7 @@ def _calculate_df_adjacent(estimators): return df_adjacent, df_err_adjacent -def _combine_df_adjacent(df_adjacent, state_ranges, df_err_adjacent=None, err_type="propagate"): +def _combine_df_adjacent(df_adjacent, state_ranges, n_tot, df_err_adjacent=None, err_type="propagate"): """ An internal function used in :func:`calculate_free_energy` to combine the free energy differences between adjacent states in different state ranges using either simple means or inverse-variance weighted means. @@ -189,6 +189,8 @@ def _combine_df_adjacent(df_adjacent, state_ranges, df_err_adjacent=None, err_ty A list of lists free energy differences between adjacent states for all replicas. state_ranges : list A list of lists of showing the state indices sampled by each replica. + n_tot : int + Number of lambda states df_err_adjacent : list, Optional A list of lists of uncertainties corresponding to the values of :code:`df_adjacent`. Notably, if :code:`df_err_adjacent` is :code:`None`, simple means will be used. Otherwise, inverse-variance weighted @@ -213,7 +215,6 @@ def _combine_df_adjacent(df_adjacent, state_ranges, df_err_adjacent=None, err_ty -------- :func:`calculate_free_energy` """ - n_tot = state_ranges[-1][-1] + 1 df, df_err, overlap_bool = [], [], [] for i in range(n_tot - 1): # df_list is a list of free energy difference between sates i and i+1 in different replicas @@ -307,7 +308,7 @@ def calculate_free_energy(data, state_ranges, df_method="MBAR", err_method="prop n_tot = state_ranges[-1] + 1 estimators = _apply_estimators(data, df_method) df_adjacent, df_err_adjacent = _calculate_df_adjacent(estimators) - df, df_err, overlap_bool = _combine_df_adjacent(df_adjacent, state_ranges, df_err_adjacent, err_type='propagate') + df, df_err, overlap_bool = _combine_df_adjacent(df_adjacent, state_ranges, n_tot, df_err_adjacent, err_type='propagate') if err_method == 'bootstrap': if seed is not None: @@ -320,7 +321,7 @@ def calculate_free_energy(data, state_ranges, df_method="MBAR", err_method="prop sampled_data = [sampled_data_all[i].iloc[b * len(data[i]):(b + 1) * len(data[i])] for i in range(n_sim)] bootstrap_estimators = _apply_estimators(sampled_data, df_method) df_adjacent, df_err_adjacent = _calculate_df_adjacent(bootstrap_estimators) - df_sampled, _, overlap_bool = _combine_df_adjacent(df_adjacent, state_ranges, df_err_adjacent, err_type='propagate') # doesn't matter what value err_type here is # noqa: E501 + df_sampled, _, overlap_bool = _combine_df_adjacent(df_adjacent, state_ranges, n_tot, df_err_adjacent, err_type='propagate') # doesn't matter what value err_type here is # noqa: E501 df_bootstrap.append(df_sampled) error_bootstrap = np.std(df_bootstrap, axis=0, ddof=1) diff --git a/ensemble_md/tests/test_analyze_free_energy.py b/ensemble_md/tests/test_analyze_free_energy.py index dc88fe7..af7a177 100644 --- a/ensemble_md/tests/test_analyze_free_energy.py +++ b/ensemble_md/tests/test_analyze_free_energy.py @@ -186,10 +186,11 @@ def test_combine_df_adjacent(): df_adjacent = [[1, 3], [4, 6]] df_err_adjacent = [[0.1, 0.1], [0.1, 0.1]] state_ranges = [[0, 1, 2], [1, 2, 3]] + n_tot = state_ranges[-1][-1] + 1 # Test 1: df_err_adjacent is None (in which case err_type is ignored) # Note that this test would lead to two harmless RuntimWarnings due to calculations like np.std([1], ddof=1), which return NaN # noqa: E501 - results = analyze_free_energy._combine_df_adjacent(df_adjacent, state_ranges, None, "propagate") + results = analyze_free_energy._combine_df_adjacent(df_adjacent, state_ranges, n_tot, None, "propagate") assert results[0] == [1, 3.5, 6] assert math.isnan(results[1][0]) assert results[1][1] == np.std([3, 4], ddof=1) @@ -197,14 +198,14 @@ def test_combine_df_adjacent(): assert results[2] == [False, True, False] # Test 2: df_err_adjacent is not None and err_type is "std" - results = analyze_free_energy._combine_df_adjacent(df_adjacent, state_ranges, df_err_adjacent, "std") + results = analyze_free_energy._combine_df_adjacent(df_adjacent, state_ranges, n_tot, df_err_adjacent, "std") assert results[0] == [1, 3.5, 6] np.testing.assert_array_almost_equal(results[1], [0.1, np.std([3, 4], ddof=1), 0.1]) assert results[2] == [False, True, False] # Test 3: df_err_adjacent is not None and err_type is "propagate" df_err_adjacent = [[0.1, 0.1], [0.2, 0.1]] # make the errs different so that the weighted mean will not be equal to simple mean # noqa: E501 - results = analyze_free_energy._combine_df_adjacent(df_adjacent, state_ranges, df_err_adjacent, "propagate") + results = analyze_free_energy._combine_df_adjacent(df_adjacent, state_ranges, n_tot, df_err_adjacent, "propagate") assert results[0] == [1, utils.weighted_mean([3, 4], [0.1, 0.2])[0], 6] assert results[1] == [0.1, utils.weighted_mean([3, 4], [0.1, 0.2])[1], 0.1] assert results[2] == [False, True, False] From 703f1dd6708381c8abe519284e1c3f50581f4895 Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Fri, 7 Mar 2025 15:32:21 -0700 Subject: [PATCH 28/32] Fix FE estimates for MTREXEE --- ensemble_md/analysis/analyze_free_energy.py | 21 ++++++++++++------- ensemble_md/tests/test_analyze_free_energy.py | 7 +++---- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/ensemble_md/analysis/analyze_free_energy.py b/ensemble_md/analysis/analyze_free_energy.py index 4ca609b..5ce7efb 100644 --- a/ensemble_md/analysis/analyze_free_energy.py +++ b/ensemble_md/analysis/analyze_free_energy.py @@ -178,7 +178,7 @@ def _calculate_df_adjacent(estimators): return df_adjacent, df_err_adjacent -def _combine_df_adjacent(df_adjacent, state_ranges, n_tot, df_err_adjacent=None, err_type="propagate"): +def _combine_df_adjacent(df_adjacent, state_ranges, df_err_adjacent=None, err_type="propagate"): """ An internal function used in :func:`calculate_free_energy` to combine the free energy differences between adjacent states in different state ranges using either simple means or inverse-variance weighted means. @@ -215,6 +215,7 @@ def _combine_df_adjacent(df_adjacent, state_ranges, n_tot, df_err_adjacent=None, -------- :func:`calculate_free_energy` """ + n_tot = state_ranges[-1][-1] + 1 df, df_err, overlap_bool = [], [], [] for i in range(n_tot - 1): # df_list is a list of free energy difference between sates i and i+1 in different replicas @@ -248,7 +249,7 @@ def _combine_df_adjacent(df_adjacent, state_ranges, n_tot, df_err_adjacent=None, return df, df_err, overlap_bool -def calculate_free_energy(data, state_ranges, df_method="MBAR", err_method="propagate", n_bootstrap=None, seed=None, MTREXEE=False): +def calculate_free_energy(data, state_ranges, df_method="MBAR", err_method="propagate", n_bootstrap=None, seed=None, MTREXEE=False): # noqa: E501 """ Caculates the averaged free energy profile with the chosen method given :math:`u_{nk}` or :math:`dH/dλ` data obtained from all replicas of the REXEE simulation. Available methods include TI, BAR, and MBAR. TI @@ -307,8 +308,11 @@ def calculate_free_energy(data, state_ranges, df_method="MBAR", err_method="prop else: n_tot = state_ranges[-1] + 1 estimators = _apply_estimators(data, df_method) - df_adjacent, df_err_adjacent = _calculate_df_adjacent(estimators) - df, df_err, overlap_bool = _combine_df_adjacent(df_adjacent, state_ranges, n_tot, df_err_adjacent, err_type='propagate') + if MTREXEE is False: + df_adjacent, df_err_adjacent = _calculate_df_adjacent(estimators) + df, df_err, overlap_bool = _combine_df_adjacent(df_adjacent, state_ranges, df_err_adjacent, err_type='propagate') # noqa: E501 + else: + df, df_err = _calculate_df_adjacent(estimators) if err_method == 'bootstrap': if seed is not None: @@ -320,15 +324,18 @@ def calculate_free_energy(data, state_ranges, df_method="MBAR", err_method="prop for b in range(n_bootstrap): sampled_data = [sampled_data_all[i].iloc[b * len(data[i]):(b + 1) * len(data[i])] for i in range(n_sim)] bootstrap_estimators = _apply_estimators(sampled_data, df_method) - df_adjacent, df_err_adjacent = _calculate_df_adjacent(bootstrap_estimators) - df_sampled, _, overlap_bool = _combine_df_adjacent(df_adjacent, state_ranges, n_tot, df_err_adjacent, err_type='propagate') # doesn't matter what value err_type here is # noqa: E501 + if MTREXEE is False: + df_adjacent, df_err_adjacent = _calculate_df_adjacent(bootstrap_estimators) + df_sampled, _, overlap_bool = _combine_df_adjacent(df_adjacent, state_ranges, df_err_adjacent, err_type='propagate') # doesn't matter what value err_type here is # noqa: E501 + else: + df_sampled, _ = _calculate_df_adjacent(bootstrap_estimators) df_bootstrap.append(df_sampled) error_bootstrap = np.std(df_bootstrap, axis=0, ddof=1) # Replace the value in df_err with value in error_bootstrap if df_err corresponds to # the df between overlapping states for i in range(n_tot - 1): - if overlap_bool[i] is True: + if MTREXEE is True or overlap_bool[i] is True: print(f'Replaced the propagated error with the bootstrapped error for states {i} and {i + 1}: {df_err[i]:.5f} -> {error_bootstrap[i]:.5f}.') # noqa: E501 df_err[i] = error_bootstrap[i] elif err_method == 'propagate': diff --git a/ensemble_md/tests/test_analyze_free_energy.py b/ensemble_md/tests/test_analyze_free_energy.py index af7a177..dc88fe7 100644 --- a/ensemble_md/tests/test_analyze_free_energy.py +++ b/ensemble_md/tests/test_analyze_free_energy.py @@ -186,11 +186,10 @@ def test_combine_df_adjacent(): df_adjacent = [[1, 3], [4, 6]] df_err_adjacent = [[0.1, 0.1], [0.1, 0.1]] state_ranges = [[0, 1, 2], [1, 2, 3]] - n_tot = state_ranges[-1][-1] + 1 # Test 1: df_err_adjacent is None (in which case err_type is ignored) # Note that this test would lead to two harmless RuntimWarnings due to calculations like np.std([1], ddof=1), which return NaN # noqa: E501 - results = analyze_free_energy._combine_df_adjacent(df_adjacent, state_ranges, n_tot, None, "propagate") + results = analyze_free_energy._combine_df_adjacent(df_adjacent, state_ranges, None, "propagate") assert results[0] == [1, 3.5, 6] assert math.isnan(results[1][0]) assert results[1][1] == np.std([3, 4], ddof=1) @@ -198,14 +197,14 @@ def test_combine_df_adjacent(): assert results[2] == [False, True, False] # Test 2: df_err_adjacent is not None and err_type is "std" - results = analyze_free_energy._combine_df_adjacent(df_adjacent, state_ranges, n_tot, df_err_adjacent, "std") + results = analyze_free_energy._combine_df_adjacent(df_adjacent, state_ranges, df_err_adjacent, "std") assert results[0] == [1, 3.5, 6] np.testing.assert_array_almost_equal(results[1], [0.1, np.std([3, 4], ddof=1), 0.1]) assert results[2] == [False, True, False] # Test 3: df_err_adjacent is not None and err_type is "propagate" df_err_adjacent = [[0.1, 0.1], [0.2, 0.1]] # make the errs different so that the weighted mean will not be equal to simple mean # noqa: E501 - results = analyze_free_energy._combine_df_adjacent(df_adjacent, state_ranges, n_tot, df_err_adjacent, "propagate") + results = analyze_free_energy._combine_df_adjacent(df_adjacent, state_ranges, df_err_adjacent, "propagate") assert results[0] == [1, utils.weighted_mean([3, 4], [0.1, 0.2])[0], 6] assert results[1] == [0.1, utils.weighted_mean([3, 4], [0.1, 0.2])[1], 0.1] assert results[2] == [False, True, False] From 18eff2f1f5be53c4141ebf6d3efdd8dc22340197 Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Fri, 7 Mar 2025 15:32:54 -0700 Subject: [PATCH 29/32] Fix linting --- ensemble_md/cli/run_REXEE.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ensemble_md/cli/run_REXEE.py b/ensemble_md/cli/run_REXEE.py index f5b300d..247a2d2 100644 --- a/ensemble_md/cli/run_REXEE.py +++ b/ensemble_md/cli/run_REXEE.py @@ -318,11 +318,11 @@ def main(): if rank == 0: # If previous swaps were performed undo them for j in range(REXEE.n_sim): - gro_backup = f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout_backup.gro' + gro_backup = f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout_backup.gro' # noqa: E501 gro = f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout.gro' if os.path.exists(gro_backup): os.rename(gro_backup, gro) - + for j in range(len(swap_list)): print('\nModifying the coordinates of the following output GRO files ...') # gro_1 and gro_2 are the simlation outputs (that we want to back up) and the inputs to modify_coords # noqa: E501 From ee284de58f52625ddfac73fa70b52fd1c0334ca1 Mon Sep 17 00:00:00 2001 From: Anika Date: Fri, 7 Mar 2025 15:33:54 -0700 Subject: [PATCH 30/32] Fix error --- ensemble_md/cli/run_REXEE.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ensemble_md/cli/run_REXEE.py b/ensemble_md/cli/run_REXEE.py index f5b300d..78474f1 100644 --- a/ensemble_md/cli/run_REXEE.py +++ b/ensemble_md/cli/run_REXEE.py @@ -318,8 +318,8 @@ def main(): if rank == 0: # If previous swaps were performed undo them for j in range(REXEE.n_sim): - gro_backup = f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout_backup.gro' - gro = f'{REXEE.working_dir}/sim_{swap_list[j][0]}/iteration_{i-1}/confout.gro' + gro_backup = f'{REXEE.working_dir}/sim_{j}/iteration_{i-1}/confout_backup.gro' + gro = f'{REXEE.working_dir}/sim_{j}/iteration_{i-1}/confout.gro' if os.path.exists(gro_backup): os.rename(gro_backup, gro) From 86f3413d3b6ace6ee9fe4e09b8f0d9ee85158611 Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Fri, 14 Mar 2025 10:38:44 -0600 Subject: [PATCH 31/32] update FE for mtrexee --- ensemble_md/analysis/analyze_free_energy.py | 35 +++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/ensemble_md/analysis/analyze_free_energy.py b/ensemble_md/analysis/analyze_free_energy.py index 5ce7efb..cc005cc 100644 --- a/ensemble_md/analysis/analyze_free_energy.py +++ b/ensemble_md/analysis/analyze_free_energy.py @@ -249,6 +249,36 @@ def _combine_df_adjacent(df_adjacent, state_ranges, df_err_adjacent=None, err_ty return df, df_err, overlap_bool +def _calculate_df(estimators): + """ + An internal function used in :func:`calculate_free_energy` to calculate a list of free energies between adjacent + states for all replicas. + + Parameters + ---------- + estimators : list + A list of estimators fitting the input data for all replicas. With this, the user + can access all the free energies and their associated uncertainties for all states and replicas. + In our code, these estimators come from the function :func:`_apply_estimators`. + + Returns + ------- + df : float + Free energy differences between for specified replica. + df_err : float + Uncertainties corresponding to the values in :code:`df`. + + See also + -------- + :func:`calculate_free_energy` + """ + l = np.linspace(0, 1, num=len(estimators[0].index)) + estimators[0].index = l + estimators[0].columns = l + est = estimators[0].loc[0, 1] + return est + + def calculate_free_energy(data, state_ranges, df_method="MBAR", err_method="propagate", n_bootstrap=None, seed=None, MTREXEE=False): # noqa: E501 """ Caculates the averaged free energy profile with the chosen method given :math:`u_{nk}` or :math:`dH/dλ` data @@ -308,11 +338,12 @@ def calculate_free_energy(data, state_ranges, df_method="MBAR", err_method="prop else: n_tot = state_ranges[-1] + 1 estimators = _apply_estimators(data, df_method) + print(estimators) if MTREXEE is False: df_adjacent, df_err_adjacent = _calculate_df_adjacent(estimators) df, df_err, overlap_bool = _combine_df_adjacent(df_adjacent, state_ranges, df_err_adjacent, err_type='propagate') # noqa: E501 else: - df, df_err = _calculate_df_adjacent(estimators) + df, df_err = _calculate_df(estimators) if err_method == 'bootstrap': if seed is not None: @@ -328,7 +359,7 @@ def calculate_free_energy(data, state_ranges, df_method="MBAR", err_method="prop df_adjacent, df_err_adjacent = _calculate_df_adjacent(bootstrap_estimators) df_sampled, _, overlap_bool = _combine_df_adjacent(df_adjacent, state_ranges, df_err_adjacent, err_type='propagate') # doesn't matter what value err_type here is # noqa: E501 else: - df_sampled, _ = _calculate_df_adjacent(bootstrap_estimators) + df_sampled, _ = _calculate_df(bootstrap_estimators) df_bootstrap.append(df_sampled) error_bootstrap = np.std(df_bootstrap, axis=0, ddof=1) From 760a0cb4b41a02ce2c0c05f14a2984be247198aa Mon Sep 17 00:00:00 2001 From: ajfriedman22 Date: Fri, 14 Mar 2025 11:56:26 -0600 Subject: [PATCH 32/32] update tests --- .../{forced-swap => random-range}/dhdl_0.xvg | 0 .../{forced-swap => random-range}/dhdl_1.xvg | 0 .../{forced-swap => random-range}/dhdl_2.xvg | 0 .../{forced-swap => random-range}/dhdl_3.xvg | 0 ensemble_md/tests/test_replica_exchange_EE.py | 36 +++++++++++-------- 5 files changed, 21 insertions(+), 15 deletions(-) rename ensemble_md/tests/data/dhdl/{forced-swap => random-range}/dhdl_0.xvg (100%) rename ensemble_md/tests/data/dhdl/{forced-swap => random-range}/dhdl_1.xvg (100%) rename ensemble_md/tests/data/dhdl/{forced-swap => random-range}/dhdl_2.xvg (100%) rename ensemble_md/tests/data/dhdl/{forced-swap => random-range}/dhdl_3.xvg (100%) diff --git a/ensemble_md/tests/data/dhdl/forced-swap/dhdl_0.xvg b/ensemble_md/tests/data/dhdl/random-range/dhdl_0.xvg similarity index 100% rename from ensemble_md/tests/data/dhdl/forced-swap/dhdl_0.xvg rename to ensemble_md/tests/data/dhdl/random-range/dhdl_0.xvg diff --git a/ensemble_md/tests/data/dhdl/forced-swap/dhdl_1.xvg b/ensemble_md/tests/data/dhdl/random-range/dhdl_1.xvg similarity index 100% rename from ensemble_md/tests/data/dhdl/forced-swap/dhdl_1.xvg rename to ensemble_md/tests/data/dhdl/random-range/dhdl_1.xvg diff --git a/ensemble_md/tests/data/dhdl/forced-swap/dhdl_2.xvg b/ensemble_md/tests/data/dhdl/random-range/dhdl_2.xvg similarity index 100% rename from ensemble_md/tests/data/dhdl/forced-swap/dhdl_2.xvg rename to ensemble_md/tests/data/dhdl/random-range/dhdl_2.xvg diff --git a/ensemble_md/tests/data/dhdl/forced-swap/dhdl_3.xvg b/ensemble_md/tests/data/dhdl/random-range/dhdl_3.xvg similarity index 100% rename from ensemble_md/tests/data/dhdl/forced-swap/dhdl_3.xvg rename to ensemble_md/tests/data/dhdl/random-range/dhdl_3.xvg diff --git a/ensemble_md/tests/test_replica_exchange_EE.py b/ensemble_md/tests/test_replica_exchange_EE.py index b4a5549..ecdf5d4 100644 --- a/ensemble_md/tests/test_replica_exchange_EE.py +++ b/ensemble_md/tests/test_replica_exchange_EE.py @@ -676,6 +676,27 @@ def test_identify_swappable_pairs(self, params_dict): assert swap_index == [] assert states_for_swap == [] + # Case 4: Random Range + REXEE.proposal = 'random_range' + REXEE.state_ranges = [list(range(i, i + 7)) for i in [0, 7, 14, 21]] + states = [[6, 7], [13, 14], [20, 21]] + REXEE = get_REXEE_instance(params_dict) + REXEE.n_tot = 28 + REXEE.s = 7 + REXEE.template['nstdhdl'] = 100 + REXEE.template['nstxout'] = 1000 + REXEE.template['n_sim'] = 4 + + dhdl_files = [ + os.path.join(input_path, f"dhdl/random-range/dhdl_{i}.xvg") for i in range(REXEE.n_sim) + ] + swappables, swap_index, states_for_swap = REXEE.identify_swappable_pairs(states, REXEE.state_ranges, dhdl_files) + + #assert swappables[0] == [0, 1] + assert swap_index[0][0] in [14, 15, 16] + assert swap_index[0][1] in [10, 12, 16, 19] + assert states_for_swap[0] == [6, 7] + def test_propose_swap(self, params_dict): random.seed(0) REXEE = get_REXEE_instance(params_dict) @@ -839,21 +860,6 @@ def test_accept_or_reject(self, params_dict): assert swap_bool_2 is False assert swap_bool_3 is True - def test_deter_swap_index(self, params_dict): - REXEE = get_REXEE_instance(params_dict) - REXEE.n_tot = 28 - REXEE.s = 7 - REXEE.template['nstdhdl'] = 100 - REXEE.template['nstxout'] = 1000 - REXEE.template['n_sim'] = 4 - - dhdl_files = [ - os.path.join(input_path, f"dhdl/forced-swap/dhdl_{i}.xvg") for i in range(REXEE.n_sim) - ] - swap_index, swap_state = REXEE._deter_swap_index([0, 1], dhdl_files, [[6, 7], [13, 14], [20, 21]]) - assert swap_index[0] in [14, 15, 16] - assert swap_index[1] in [10, 16, 19] - assert swap_state == [6, 7] def test_weight_correction(self, params_dict): REXEE = get_REXEE_instance(params_dict)