def test_minus_ensembles(self): good_traj_seq = [-0.51, -0.49, -0.40, -0.52, -0.48, -0.51] # AXXAXA bad_traj_seq = [-0.51, -0.49, -0.05, -0.52, -0.48, -0.51] # AXBAXA minus_dict = self.mstis.special_ensembles['minus'] from_A = self.mstis.from_state[self.stateA] trans_to_minus = { trans: minus for (minus, transitions) in minus_dict.items() for trans in transitions } minus_A = trans_to_minus[from_A] good_minus_traj = make_1d_traj(good_traj_seq) bad_minus_traj = make_1d_traj(bad_traj_seq) # test that the call works assert_equal(minus_A(good_minus_traj), True) assert_equal(minus_A(bad_minus_traj), False) # test that the can_append works for the good traj good_building_traj = paths.Trajectory([]) for (i, snap) in enumerate(good_minus_traj): good_building_traj.append(snap) if not minus_A.can_append(good_building_traj, trusted=True): break assert_equal(len(good_building_traj), len(good_minus_traj)) # test that the can_append works for the bad traj bad_building_traj = paths.Trajectory([]) for (i, snap) in enumerate(bad_minus_traj): bad_building_traj.append(snap) if not minus_A.can_append(bad_building_traj, trusted=True): break assert_equal(len(bad_building_traj), 3)
def __init__(self, multiple_binding_ensemble, subselector=None): self.multiple_binding_ensemble = multiple_binding_ensemble if subselector is None: subselector = paths.UniformSelector() self.subselector = subselector # cache the previously tested trajectory and the resulting # subtrajectory. This avoids wasteful recalc for most cases of # multiple use of `f`, `pick`, `sum_bias` for the same input traj self._cached_subtraj = paths.Trajectory([]) self._cached_traj = paths.Trajectory([])
def test_internalize(self): snap = self.snapshots[0] internal = snap.internalize() np.testing.assert_array_equal(snap.xyz, internal.xyz) np.testing.assert_array_equal(snap.velocities, internal.velocities) np.testing.assert_array_equal(snap.box_vectors, internal.box_vectors) # the way to do it for a trajectory traj_i = paths.Trajectory([s.internalize() for s in self.snapshots]) traj_e = paths.Trajectory(self.snapshots) np.testing.assert_array_equal(traj_i.xyz, traj_e.xyz)
def sequential_main(self): tps_storage = paths.Storage(self.tps_file, mode='r') # get initial conditions, and stick them in files for each task initial_snapshots = self.select_snapshots(tps_storage) engine = self.most_probable_engine(initial_snapshots) randomizer = create_randomizer(engine) if self.output: out_storage = paths.Storage(self.output, mode='w') out_storage.save(engine) out_storage.tags['randomizer'] = randomizer out_storage.save(paths.Trajectory(initial_snapshots)) task_files = self.write_task_files(initial_snapshots, engine, randomizer) # tps_storage.close() # this is the part that will be executed remotely result_list = [ file_snapshots_committor(task_file, self.n_per_snapshot) for task_file in task_files ] runs = self.create_individual_runs(tps_storage, result_list) tps_storage.close() if self.output: out_storage.tags['individual_runs'] = runs out_storage.close() return initial_snapshots, runs
def test_max_length_rejected(self): stateA = paths.EmptyVolume() # will run indefinitely stateB = paths.EmptyVolume() tps = A2BEnsemble(stateA, stateB) self.engine.options['n_frames_max'] = 10 self.engine.on_max_length = 'fail' init_traj = paths.Trajectory([template] * 5) init_samp = paths.SampleSet([paths.Sample( trajectory=init_traj, replica=0, ensemble=tps )]) mover = paths.BackwardShootMover( ensemble=tps, selector=paths.UniformSelector(), engine=self.engine ) change = mover.move(init_samp) assert(isinstance(change, paths.RejectedMaxLengthSampleMoveChange)) assert_equal(change.details.rejection_reason, 'max_length') assert_equal( len(change.samples[0].trajectory), self.engine.n_frames_max) newsamp = init_samp.apply_samples(change) assert_equal(len(newsamp), 1) # make sure there is no change! assert_equal(init_samp[0].trajectory, init_traj)
def test_safemode(self): fname = data_filename("cv_storage_safemode_test.nc") if os.path.isfile(fname): os.remove(fname) cv = paths.CoordinateFunctionCV('cv', lambda x: x) traj = paths.Trajectory(list(self.traj)) template = traj[0] storage_w = paths.Storage(fname, "w") storage_w.snapshots.save(template) storage_w.cvs.save(cv) storage_w.close() storage_r = paths.Storage(fname, 'r') # default safemode = False assert (storage_r.simplifier.safemode is False) cv_r = storage_r.cvs[0] assert (cv_r == cv) assert (cv.cv_callable is not None) storage_r.close() storage_r = paths.Storage(fname, 'r') storage_r.simplifier.safemode = True cv_r = storage_r.cvs[0] assert (cv_r == cv) assert (cv_r.cv_callable is None) storage_r.close()
def make_1d_traj(coordinates, velocities=None, engine=None): if velocities is None: velocities = [1.0]*len(coordinates) try: _ = len(velocities) except TypeError: velocities = [velocities] * len(coordinates) if engine is None: engine = toys.Engine( {}, toys.Topology( n_spatial=3, masses=[1.0, 1.0, 1.0], pes=None ) ) traj = [] for (pos, vel) in zip(coordinates, velocities): snap = toys.Snapshot( coordinates=np.array([[pos, 0, 0]]), velocities=np.array([[vel, 0, 0]]), engine=engine ) traj.append(snap) return paths.Trajectory(traj)
def test_nan_rejected(self): stateA = paths.EmptyVolume() # will run indefinitely stateB = paths.EmptyVolume() tps = A2BEnsemble(stateA, stateB) self.engine.n_frames_max = 10 init_traj = paths.Trajectory([nan_causing_template] * 5) init_samp = paths.SampleSet([paths.Sample( trajectory=init_traj, replica=0, ensemble=tps )]) mover = paths.BackwardShootMover( ensemble=tps, selector=paths.UniformSelector(), engine=self.engine ) change = mover.move(init_samp) assert (isinstance(change, paths.RejectedNaNSampleMoveChange)) assert_equal(change.details.rejection_reason, 'nan') # since we shoot, we start with a shorter trajectory assert(len(change.samples[0].trajectory) < len(init_traj)) newsamp = init_samp.apply_samples(change) assert_equal(len(newsamp), 1) # make sure there is no change! assert_equal(init_samp[0].trajectory, init_traj)
def run(self, n_per_snapshot, as_chain=False): """Run the simulation. Parameters ---------- n_per_snapshot : int number of shots per snapshot as_chain : bool if as_chain is False (default), then the input to the modifier is always the original snapshot. If as_chain is True, then the input to the modifier is the previous (modified) snapshot. Useful for modifications that can't cover the whole range from a given snapshot. """ self.step = 0 snap_num = 0 for snapshot in self.initial_snapshots: start_snap = snapshot # do what we need to get the snapshot set up for step in range(n_per_snapshot): paths.tools.refresh_output( "Working on snapshot %d / %d; shot %d / %d" % ( snap_num+1, len(self.initial_snapshots), step+1, n_per_snapshot ), output_stream=self.output_stream, refresh=self.allow_refresh ) if as_chain: start_snap = self.randomizer(start_snap) else: start_snap = self.randomizer(snapshot) sample_set = paths.SampleSet([ paths.Sample(replica=0, trajectory=paths.Trajectory([start_snap]), ensemble=self.starting_ensemble) ]) sample_set.sanity_check() new_pmc = self.mover.move(sample_set) samples = new_pmc.results new_sample_set = sample_set.apply_samples(samples) mcstep = MCStep( simulation=self, mccycle=self.step, previous=sample_set, active=new_sample_set, change=new_pmc ) if self.storage is not None: self.storage.steps.save(mcstep) if self.step % self.save_frequency == 0: self.sync_storage() self.step += 1 snap_num += 1
def run(self, n_steps): most_recent_state = None first_interface_exit = {p: -1 for p in self.flux_pairs} last_state_visit = {s: -1 for s in self.states} was_in_interface = {p: None for p in self.flux_pairs} local_traj = paths.Trajectory([self.initial_snapshot]) self.engine.current_snapshot = self.initial_snapshot self.engine.start() for step in xrange(n_steps): frame = self.engine.generate_next_frame() # update the most recent state if we're in a state state = None # no state at all for s in self.states: if s(frame): state = s if state: last_state_visit[state] = step if state is not most_recent_state: # we've made a transition: on the first entrance into # this state, we reset the last_interface_exit state_flux_pairs = [p for p in self.flux_pairs if p[0] == state] for p in state_flux_pairs: first_interface_exit[p] = -1 # if this isn't the first change of state, we add the # transition if most_recent_state: self.transition_count.append((state, step)) most_recent_state = state # update whether we've left any interface for p in self.flux_pairs: state = p[0] interface = p[1] is_in_interface = interface(frame) # by line: (1) this is a crossing; (2) the most recent state # is correct; (3) this is the FIRST crossing first_exit_condition = ( not is_in_interface and was_in_interface[p] # crossing and state is most_recent_state # correct recent state and first_interface_exit[p] < last_state_visit[state] ) if first_exit_condition: first_exit = first_interface_exit[p] # successful exit if 0 < first_exit < last_state_visit[state]: flux_time_range = (step, first_exit) self.flux_events[p].append(flux_time_range) first_interface_exit[p] = step was_in_interface[p] = is_in_interface if self.storage is not None: local_traj += [frame] self.engine.stop(local_traj) if self.storage is not None: self.storage.save(local_traj)
def _eval(self, items): trajectory = paths.Trajectory(items) # create an MDtraj trajectory out of it ptraj = trajectory.md() # run the featurizer return self._instance.partial_transform(ptraj)
def _eval(self, items): trajectory = paths.Trajectory(items) # create an mdtraj trajectory out of it ptraj = trajectory_to_mdtraj(trajectory, self.topology.mdtraj) # run the featurizer return self._instance.partial_transform(ptraj)
def _to_list_of_trajectories(trajectories): if isinstance(trajectories, Trajectory): trajectories = [trajectories] elif isinstance(trajectories, paths.Sample): trajectories = [trajectories.trajectory] elif isinstance(trajectories, paths.SampleSet): trajectories = [s.trajectory for s in trajectories] elif isinstance(trajectories, list): if len(trajectories) > 0: trajectories = [ obj.trajectory if isinstance(obj, paths.Sample) else obj for obj in trajectories ] elif isinstance(trajectories, paths.BaseSnapshot): return paths.Trajectory([trajectories]) elif isinstance(trajectories, paths.BaseSnapshot): return paths.Trajectory([trajectories]) return trajectories
def make_trajectory(string_representation): str2frame = { "B": bound_frame, "U": unbound_frame, "C": contact_frame, "X": excl_vol_frame, "O": other_frame } return paths.Trajectory( [str2frame[char].copy() for char in string_representation.upper()])
def test_storage_attribute_function(self): import os # test all combinations of (1) with and without UUIDs, # (2) using partial yes, no all of these must work for allow_incomplete in (True, False): # print('ALLOW INCOMPLETE', allow_incomplete) fname = data_filename("attr_storage_test.nc") if os.path.isfile(fname): os.remove(fname) traj = paths.Trajectory(list(self.traj_simple)) template = traj[0] storage_w = paths.Storage(fname, "w") storage_w.snapshots.save(template) storage_w.trajectories.save(traj) # compute distance in x[0] attr1 = FunctionPseudoAttribute( 'f1', paths.Trajectory, lambda x: x[0].coordinates[0] - x[-1].coordinates[ 0]).with_diskcache(allow_incomplete=allow_incomplete) storage_w.save(attr1) # let's mess up the order in which we save and # include reversed ones as well storage_w.trajectories.save(traj[3:]) storage_w.snapshots.save(traj[1].reversed) storage_w.trajectories.save(traj.reversed) # this should be ignored for all is saved already storage_w.trajectories.save(traj) storage_w.close() storage_r = paths.Storage(fname, 'r') rattr1 = storage_r.attributes['f1'] assert (rattr1._store_dict) attr_cache = rattr1._store_dict.value_store assert (attr_cache.allow_incomplete == allow_incomplete) for idx, traj in enumerate(storage_r.trajectories): if not allow_incomplete or attr_cache[traj] is not None: assert_close_unit(attr_cache[traj], attr1(traj)) storage_r.close() if os.path.isfile(fname): os.remove(fname)
def map_trajectory_to_ensembles(trajectory, ensembles): """Return SampleSet mapping one trajectory to all ensembles. One common approach to starting a simulation is to take a single transition trajectory (which satisfies all ensembles) and use it as the starting point for all ensembles. """ return SampleSet([ Sample.initial_sample( replica=ensembles.index(e), trajectory=paths.Trajectory(trajectory.as_proxies()), # copy ensemble=e) for e in ensembles ])
def shooting_move_info(): t0 = make_1d_traj( [-0.1, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.1]) t1 = make_1d_traj([-0.11, 2.1]) t2 = make_1d_traj([5.2, 7.2, 9.2, 10.12]) t3 = make_1d_traj([-0.13, 2.3, 5.3, 8.3]) t4 = make_1d_traj([-0.14, 2.4, 4.4, 6.4]) out1 = paths.Trajectory(t1 + t0[4:]) out2 = paths.Trajectory(out1[0:3] + t2) out3 = paths.Trajectory(t3 + out2[5:]) # REJECT THIS out4 = paths.Trajectory(t4 + out2[4:]) # for traj in [t0, out1, out2, out3, out4]: # print [s.xyz[0][0] for s in traj] # replica, full trial, shooting idx, one-way trial, direction moves = [(0, out1, 4, True, t1, -1), (0, out2, 2, True, t2, +1), (0, out3, 5, False, t3, -1), (0, out4, 4, True, t4, -1)] initial_sample = paths.Sample(replica=0, trajectory=t0, ensemble=tps_ensemble) return initial_sample, moves
def test_probability_ratio_modified_coordinates(self, new_coord, expected): # Test if probability ratio still works when coordinates are modified mytraj = make_1d_traj( coordinates=[-0.5, -0.4, -0.3, -0.1, 0.1, 0.2, 0.3, 0.5]) idx = self.sel.pick(mytraj) frame = mytraj[idx] # Alter 0.1 to 0.11 and replace the original snapshot with the modded # one mod_frame = frame.copy_with_replacement(coordinates=[[new_coord]]) mod_traj = mytraj[:idx] mod_traj += paths.Trajectory([mod_frame]) mod_traj += mytraj[idx + 1:] prob = self.sel.probability_ratio(frame, mytraj, mod_traj, mod_frame) assert prob == expected
def md(snapshot): """ Returns ------- md : mdtraj.Trajectory the actual trajectory object. Can be used with all functions from mdtraj Notes ----- Rather slow since the topology has to be made each time. Try to avoid it. This will only work if the engine has an mdtraj_topology property. """ if snapshot.statics is not None: return paths.Trajectory([snapshot]).to_mdtraj()
def get_all_frames(self, label): """Return all frames for a given label as a flattened trajectory. Parameters ---------- label : str the label used for this state Returns ------- ``paths.Trajectory`` all frames in this trajectory with the given label """ return sum(self.get_segments(label), paths.Trajectory([]))
def _update(self, trajectory, direction=None): logger.debug("BEGIN MultipleBindingEnsembleCache._update") def _debug_most_common(): if logger.isEnabledFor(logging.DEBUG): n_contacts = self.ensemble.stable_contact_state.n_contacts most_common = \ self.contact_frequency.residue_contacts.most_common() logger.debug("most_common: " + str(most_common[:n_contacts])) if direction is None: direction = self.direction direction = clean_direction(direction) n_frames = self.ensemble.stable_contact_state.n_frames self.initial_frame = trajectory[0] self.final_frame = trajectory[-1] add_frame = {FWD: trajectory[-1], BKWD: trajectory[0]}[direction] add_freq = self._make_contact_freq(paths.Trajectory([add_frame])) logger.debug("Adding frame to contact frequency") self.contact_frequency.add_contact_frequency(add_freq) _debug_most_common() if len(trajectory) > n_frames: sub_index = {FWD: -n_frames - 1, BKWD: n_frames}[direction] sub_frame = trajectory[sub_index] sub_freq = self._make_contact_freq(paths.Trajectory([sub_frame])) logger.debug("Subtracting frame %d from contact frequency", sub_index) self.contact_frequency.subtract_contact_frequency(sub_freq) _debug_most_common() logger.debug("Contact frequency based on length %d, total length %d", self.contact_frequency.n_frames, len(trajectory)) logger.debug("END MultipleBindingEnsembleCache._update")
def test_reversed(self): traj = paths.Trajectory(self.snapshots) traj_rev = traj.reversed for idx in range(len(traj)): snap = traj[idx] snap_rev = traj_rev[-idx-1] np.testing.assert_array_equal(snap.xyz, snap_rev.xyz) np.testing.assert_array_equal(snap.box_vectors, snap_rev.box_vectors) assert snap.velocity_direction == 1 assert snap_rev.velocity_direction == -1 np.testing.assert_array_equal(snap.velocities, -snap_rev.velocities) assert snap._reversed == snap_rev assert snap_rev._reversed == snap
def test_reduce_trajectory_box_vectors(): box = np.array([[6.70596027, 0., 0.], [0., 6.70596027, 0.], [3.35299015, 3.35299015, 4.74183893]]) snap_1 = mock_snapshot_with_box_vector(box) reduced_box = reduced_box_vectors(snap_1).value_in_unit(nm) snap_2 = mock_snapshot_with_box_vector(reduced_box) traj = paths.Trajectory([snap_1, snap_2]) red_traj = reduce_trajectory_box_vectors(traj) orig_box = traj.box_vectors red_box = red_traj.box_vectors assert not all(orig_box[0].flatten() == red_box[0].flatten()) npt.assert_allclose(red_box[0], red_box[1]) for reduced in red_box: check_reduced_box_vectors(reduced.value_in_unit(nm))
def trajectory_from_mdtraj(mdtrajectory): """ Construct a Trajectory object from an mdtraj.Trajectory object Parameters ---------- mdtrajectory : mdtraj.Trajectory Input mdtraj.Trajectory Returns ------- Trajectory the constructed Trajectory instance """ #TODO: Fix energies and move these to specialized CVs #TODO: We could also allow to have empty energies trajectory = paths.Trajectory() empty_momentum = paths.Momentum( velocities=u.Quantity(np.zeros(mdtrajectory.xyz[0].shape), u.nanometer / u.picosecond), kinetic_energy=u.Quantity(0.0, u.kilojoule_per_mole)) topology = paths.MDTrajTopology(mdtrajectory.topology) for frame_num in range(len(mdtrajectory)): # mdtraj trajectories only have coordinates and box_vectors coord = u.Quantity(mdtrajectory.xyz[frame_num], u.nanometers) if mdtrajectory.unitcell_vectors is not None: box_v = u.Quantity(mdtrajectory.unitcell_vectors[frame_num], u.nanometers) else: box_v = None config = paths.Configuration(coordinates=coord, box_vectors=box_v, potential_energy=u.Quantity( 0.0, u.kilojoule_per_mole), topology=topology) snap = paths.Snapshot(configuration=config, momentum=empty_momentum, topology=paths.MDTrajTopology( mdtrajectory.topology)) trajectory.append(snap) return trajectory
def test_storage_sync_and_complete(self): import os # test all combinations of (1) with and without UUIDs, # (2) using partial yes, no all of these must work allow_incomplete = True fname = data_filename("attr_storage_test.nc") if os.path.isfile(fname): os.remove(fname) traj = paths.Trajectory(list(self.traj_simple)) template = traj[0] storage_w = paths.Storage(fname, "w") storage_w.snapshots.save(template) storage_w.trajectories.save(traj) # compute distance in x[0] attr1 = FunctionPseudoAttribute( 'f1', paths.Trajectory, lambda x: x[0].coordinates[0] - x[-1]. coordinates[0]).with_diskcache(allow_incomplete=allow_incomplete) storage_w.save(attr1) store = storage_w.attributes.cache_store(attr1) storage_w.trajectories.complete_attribute(attr1) # check if stored values match computed ones for idx, value in zip(store.variables['index'][:], store.vars['value']): traj = storage_w.trajectories[storage_w.trajectories.vars['uuid'] [idx]] assert_close_unit(attr1(traj), value) storage_w.close() if os.path.isfile(fname): os.remove(fname)
def test_store_snapshots(self): fname = data_filename("cv_storage_test.nc") if os.path.isfile(fname): os.remove(fname) traj = paths.Trajectory(list(self.traj)) template = traj[0] for use_cache in (False, True): # print '==========================================================' # print 'UUID', use_uuid, 'CACHE', use_cache # print '==========================================================' storage_w = paths.Storage(fname, "w") storage_w.snapshots.save(template) # let's mess up the order in which we save and include # reversed ones as well assert (len(storage_w.snapshots) == 2) assert (len(storage_w.trajectories) == 0) assert (len(storage_w.stores['snapshot0']) == 2) storage_w.snapshots.save(traj[8].reversed) assert (len(storage_w.snapshots) == 4) assert (len(storage_w.trajectories) == 0) assert (len(storage_w.stores['snapshot0']) == 4) # this will store traj[6:] under pos IDX #0 storage_w.trajectories.save(traj[6:]) assert (len(storage_w.snapshots) == 10) assert (len(storage_w.trajectories) == 1) assert (len(storage_w.stores['snapshot0']) == 10) traj_rev = traj.reversed # this will store traj_rev under pos IDX #1 storage_w.trajectories.mention(traj_rev) assert (len(storage_w.snapshots) == 20) assert (len(storage_w.trajectories) == 2) assert (len(storage_w.stores['snapshot0']) == 10) # this will not do anything since traj is already saved storage_w.trajectories.save(traj_rev) assert (len(storage_w.snapshots) == 20) assert (len(storage_w.trajectories) == 2) assert (len(storage_w.stores['snapshot0']) == 10) # this will store traj under pos IDX #2 storage_w.trajectories.save(traj) assert (len(storage_w.snapshots) == 20) assert (len(storage_w.trajectories) == 3) assert (len(storage_w.stores['snapshot0']) == 20) # this will not store since traj is already stored storage_w.trajectories.save(traj) assert (len(storage_w.snapshots) == 20) assert (len(storage_w.trajectories) == 3) assert (len(storage_w.stores['snapshot0']) == 20) # we saved in this order [0f, 8r, 6f, 7f, 9f, 5r, 4r, 3r, 2r, 1r ] # these are indices [ 0, 17, 12, 14, 18, 3, 5, 7, 9, 11 ] storage_w.close() if use_cache: storage_r = paths.AnalysisStorage(fname) else: storage_r = paths.Storage(fname, 'r') storage_r.snapshots.set_caching(False) storage_r.stores['snapshot0'].set_caching(False) # check if the loaded trajectory is reproduced for s1, s2 in zip(traj, storage_r.trajectories[2]): compare_snapshot(s1, s2, True) # this is the expected order in which it is saved eff_traj = [ traj[0], traj[8].reversed, traj[6], traj[7], traj[9], traj[5].reversed, traj[4].reversed, traj[3].reversed, traj[2].reversed, traj[1].reversed, ] # load from hidden and see, if the hidden store looks as expected # we open every second snapshot from the hidden store because the # ones in between correspond to the reversed ones hidden_snapshots = storage_r.stores['snapshot0'][:] for idx in range(10): s1 = eff_traj[idx] s1r = s1.reversed s2 = hidden_snapshots[2 * idx] s2r = hidden_snapshots[2 * idx + 1] compare_snapshot(s1, s2, True) compare_snapshot(s1r, s2r, True) storage_r.close()
def _eval(self, items): trajectory = paths.Trajectory(items) t = trajectory_to_mdtraj(trajectory, self.topology.mdtraj) return self._instance.transform(t)
def _eval(self, items): trajectory = paths.Trajectory(items) t = trajectory_to_mdtraj(trajectory, self.topology.mdtraj) return self.cv_callable(t, **self.kwargs)
def _eval(self, items): trajectory = paths.Trajectory(items) return [self._instance(snap) for snap in trajectory]
def test_storage_sync(self): import os # test all combinations of (1) with and without UUIDs, # (2) using partial yes; all of these must work allow_incomplete = True # print # print for use_uuid in [True]: # print '==========================================================' # print 'UUID', use_uuid # print '==========================================================' fname = data_filename("cv_storage_test.nc") if os.path.isfile(fname): os.remove(fname) traj = paths.Trajectory(list(self.traj_simple)) template = traj[0] storage_w = paths.Storage(fname, "w") storage_w.snapshots.save(template) cv1 = paths.CoordinateFunctionCV( 'f1', lambda snapshot: snapshot.coordinates[0]).with_diskcache( allow_incomplete=allow_incomplete) # let's mess up the order in which we save and # include reversed ones as well assert (len(storage_w.snapshots) == 2) storage_w.trajectories.save(traj[6:]) assert (len(storage_w.snapshots) == 10) storage_w.snapshots.save(traj[1].reversed) assert (len(storage_w.snapshots) == 12) storage_w.save(cv1) store = storage_w.cvs.cache_store(cv1) assert (len(store.vars['value']) == 0) storage_w.snapshots.sync_cv(cv1) # nothing added to the cache so no changes assert (len(store.vars['value']) == 1) # fill the cache _ = cv1(traj) storage_w.snapshots.sync_cv(cv1) # should match the number of stored snapshots assert (len(store.vars['value']) == 6) # save the rest storage_w.trajectories.save(traj.reversed) assert (len(storage_w.snapshots) == 20) # should still be unchanged assert (len(store.vars['value']) == 6) # this should store the remaining CV values storage_w.snapshots.sync_cv(cv1) assert (len(store.vars['value']) == 10) # check if the values match for idx, value in zip(store.variables['index'][:], store.vars['value']): snap = storage_w.snapshots[storage_w.snapshots.vars['uuid'] [idx]] assert_close_unit(cv1(snap), value) storage_w.close() if os.path.isfile(fname): os.remove(fname)