def _make_fake_minus_steps(self, scheme, descriptions): network = scheme.network state_adjustment = { self.state_A: lambda x: x, self.state_B: lambda x: 1.0 - x } minus_ensemble_to_mover = {m.minus_ensemble: m for m in scheme.movers['minus']} assert_equal(set(minus_ensemble_to_mover.keys()), set(network.minus_ensembles)) steps = [] mccycle = 0 for minus_traj in descriptions: for i, minus_ensemble in enumerate(network.minus_ensembles): replica = -1 - i adjustment = state_adjustment[minus_ensemble.state_vol] traj = make_1d_traj([adjustment(s) for s in minus_traj]) assert_equal(minus_ensemble(traj), True) samp = paths.Sample(trajectory=traj, ensemble=minus_ensemble, replica=replica) sample_set = paths.SampleSet([samp]) change = paths.AcceptedSampleMoveChange( samples=[samp], mover=minus_ensemble_to_mover[samp.ensemble], details=paths.Details() ) # NOTE: this makes it so that only one ensemble is # represented in the same set at any time, which isn't quite # how it actually works. However, this is doesn't matter for # the current implementation steps.append(paths.MCStep(mccycle=mccycle, active=sample_set, change=change)) mccycle += 1 assert_equal(len(steps), 4) return steps
def test_with_minus_move_flux(self): network = self.mstis scheme = paths.DefaultScheme(network, engine=RandomMDEngine()) scheme.build_move_decision_tree() # create the minus move steps # `center` is the edge of the state/innermost interface center = {self.state_A: 0.0, self.state_B: 1.0} replica = {self.state_A: -1, self.state_B: -2} minus_ensemble_to_mover = {m.minus_ensemble: m for m in scheme.movers['minus']} state_to_minus_ensemble = {ens.state_vol: ens for ens in network.minus_ensembles} minus_changes = [] # `delta` is the change on either side for in vs. out for (state, delta) in [(self.state_A, 0.1), (self.state_B, -0.1)]: minus_ens = state_to_minus_ensemble[state] minus_mover = minus_ensemble_to_mover[minus_ens] a_in = center[state] - delta a_out = center[state] + delta # note that these trajs are equivalent to minus move # descriptions in TestMinusMoveFlux seq_1 = [a_in] + [a_out]*2 + [a_in]*5 + [a_out]*5 + [a_in] seq_2 = [a_in] + [a_out]*3 + [a_in]*3 + [a_out]*3 + [a_in] for seq in [seq_1, seq_2]: traj = make_1d_traj(seq) assert_equal(minus_ens(traj), True) samp = paths.Sample(trajectory=traj, ensemble=minus_ens, replica=replica[state]) sample_set = paths.SampleSet([samp]) change = paths.AcceptedSampleMoveChange( samples=[samp], mover=minus_mover, details=paths.Details() ) minus_changes.append(change) active = self.mstis_steps[0].active steps = [] cycle = -1 for m_change in minus_changes: cycle += 1 active = active.apply_samples(m_change.samples) step = paths.MCStep(mccycle=cycle, active=active, change=m_change) steps.append(step) for old_step in self.mstis_steps[1:]: cycle += 1 active = active.apply_samples(old_step.change.samples) step = paths.MCStep(mccycle=cycle, active=active, change=old_step.change) steps.append(step) analysis = StandardTISAnalysis( network=self.mstis, scheme=scheme, max_lambda_calcs={t: {'bin_width': 0.1, 'bin_range': (-0.1, 1.1)} for t in network.sampling_transitions}, steps=steps ) # now we actually verify correctness avg_t_in = (5.0 + 3.0) / 2 avg_t_out = (2.0 + 5.0 + 3.0 + 3.0) / 4 expected_flux = 1.0 / (avg_t_in + avg_t_out) # NOTE: Apparently this approach screws up the TCP calculation. I # think this is a problem in the fake data, not the simulation. for flux in analysis.flux_matrix.values(): assert_almost_equal(flux, expected_flux)
def move(self, input_sample, trial_trajectory, shooting_point, accepted, direction=None): """Fake a move. Parameters ---------- input_sample: :class:`paths.Sample` the input sample for this shooting move trial_trajectory: :class:`paths.Trajectory` the trial trajectory generated by this move shooting_point: :class:`paths.Snapshot` the shooting point snapshot for this trial accepted: bool whether the trial was accepted direction: +1, -1, or None direction of the shooting move (positive is forward, negative is backward). If self.pre_joined is True, the trial trajectory is reconstructed from the parts. To use the exact input trial trajectory with self.pre_joined == True, set direction=None """ initial_trajectory = input_sample.trajectory replica = input_sample.replica ensemble = input_sample.ensemble if not self.pre_joined: trial_trajectory = self.join_one_way(initial_trajectory, trial_trajectory, shooting_point, direction) # determine the direction based on trial trajectory shared = trial_trajectory.shared_subtrajectory(initial_trajectory) if len(shared) == 0: raise RuntimeError("No shared frames. " + "Were these shot from each other?") if shared[0] == trial_trajectory[0]: choice = 0 # forward submover elif shared[-1] == trial_trajectory[-1]: choice = 1 # backward submover else: # pragma: no cover raise RuntimeError("Are you sure this is 1-way shooting?") details = paths.Details( initial_trajectory=initial_trajectory, shooting_snapshot=shooting_point ) trial = paths.Sample( replica=replica, trajectory=trial_trajectory, ensemble=ensemble, parent=input_sample, # details=trial_details, mover=self.mimic.movers[choice] ) trials = [trial] # move_details = paths.MoveDetails() if accepted: inner = paths.AcceptedSampleMoveChange( samples=trials, mover=self.mimic.movers[choice], details=details ) else: inner = paths.RejectedSampleMoveChange( samples=trial, mover=self.mimic.movers[choice], details=details ) rc_details = paths.MoveDetails() rc_details.inputs = [] rc_details.choice = choice rc_details.chosen_mover = self.mimic.movers[choice] rc_details.probability = 0.5 rc_details.weights = [1, 1] return paths.RandomChoiceMoveChange( subchange=inner, mover=self.mimic, details=rc_details )