Example #1
0
    def get_lifetime_segments(trajectory, from_vol, to_vol, forbidden=None,
                              padding=[0, -1]):
        """General script to get lifetimes.

        Lifetimes for a transition between volumes are used in several other
        calculations: obviously, the state lifetime, but also the flux
        through an interface. This is a generic function to calculate that.

        Parameters
        ----------
        trajectory : :class:`.Trajectory`
            trajectory to analyze
        from_vol : :class:`.Volume`
            the volume for which this represents the lifetime: the
            trajectory segments returned are associated with the lifetime of
            `from_vol`
        to_vol : :class:`.Volume`
            the volume which indicates the end of the lifetime: a frame in
            this volume means the trajectory is no longer associated with
            `from_vol`
        forbidden : :class:`.Volume`
            if a frame is in `forbidden`, it cannot be part of the lifetime
            of `from_vol`. This isn't needed in 2-state lifetime
            calculations; however, it is useful to exclude other states
            from a flux calculation
        padding : list
            adjusts which frames are returned as list indices. That is, the
            returned segments are `full_segment[padding[0]:padding[1]]`.
            The `full_segment`s are the segments from (and including) each
            first frame in `from_vol` (after a visit to `to_vol`) until (and
            including) the first frame in `to_vol`. To get the full segment
            as output, use `padding=[None, None]`. The default is to remove
            the final frame (`padding=[0, -1]`) so that it doesn't include
            the frame in `to_vol`.

        Returns
        -------
        list of :class:`.Trajectory`
            the frames from (and including) each first entry from `to_vol`
            into `from_vol` until (and including) the next entry into
            `to_vol`, with no frames in `forbidden`, and with frames removed
            from the ends according to `padding`
        """
        if forbidden is None:
            forbidden = paths.EmptyVolume()
        ensemble_BAB = paths.SequentialEnsemble([
            paths.LengthEnsemble(1) & paths.AllInXEnsemble(to_vol),
            paths.PartInXEnsemble(from_vol) & paths.AllOutXEnsemble(to_vol),
            paths.LengthEnsemble(1) & paths.AllInXEnsemble(to_vol)
        ]) & paths.AllOutXEnsemble(forbidden)
        ensemble_AB = paths.SequentialEnsemble([
            paths.LengthEnsemble(1) & paths.AllInXEnsemble(from_vol),
            paths.OptionalEnsemble(paths.AllOutXEnsemble(to_vol)),
            paths.LengthEnsemble(1) & paths.AllInXEnsemble(to_vol) 
        ])
        BAB_split = ensemble_BAB.split(trajectory)
        AB_split = [ensemble_AB.split(part)[0] for part in BAB_split]
        return [subtraj[padding[0]:padding[1]] for subtraj in AB_split]
    def test_subtrajectory_indices(self):
        # simplify more complicated expressions
        stateA = self.stateA
        stateB = self.stateB
        pretraj = [
            0.20, 0.30, 0.60, 0.40, 0.65, 2.10, 2.20, 2.60, 2.10, 0.80, 0.55,
            0.40, 0.20
        ]
        # 00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12
        #  A,  A,  I,  A,  I,  B,  B,  X,  B,  X,  I,  A,  A
        trajectory = make_1d_traj(coordinates=pretraj,
                                  velocities=[1.0] * len(pretraj))
        ensemble_A = paths.AllInXEnsemble(stateA)
        ensemble_B = paths.AllInXEnsemble(stateB)
        ensemble_ABA = paths.SequentialEnsemble([
            paths.AllInXEnsemble(stateA) & paths.LengthEnsemble(1),
            paths.PartInXEnsemble(stateB) & paths.AllOutXEnsemble(stateA),
            paths.AllInXEnsemble(stateA) & paths.LengthEnsemble(1)
        ])
        subtrajectoriesA = ensemble_A.split(trajectory, overlap=0)
        subtrajectoriesB = ensemble_B.split(trajectory, overlap=0)
        subtrajectoriesABA = ensemble_ABA.split(trajectory)

        # make sure we have the trajectories we expect
        assert_equal(len(subtrajectoriesA), 3)
        assert_equal(len(subtrajectoriesB), 2)
        assert_equal(len(subtrajectoriesABA), 1)
        # the following assertions check that the subtrajectories are the
        # ones that we expect; the numbers here are linked to the indices
        # we'll test next
        assert_equal(subtrajectoriesA[0], trajectory[0:2])
        assert_equal(subtrajectoriesA[1], trajectory[3:4])
        assert_equal(subtrajectoriesA[2], trajectory[11:13])
        assert_equal(subtrajectoriesB[0], trajectory[5:7])
        assert_equal(subtrajectoriesB[1], trajectory[8:9])
        assert_equal(subtrajectoriesABA[0], trajectory[3:12])
        # now we run the subtrajectory_indices function and test it
        indicesA = trajectory.subtrajectory_indices(subtrajectoriesA)
        indicesB = trajectory.subtrajectory_indices(subtrajectoriesB)
        indicesABA = trajectory.subtrajectory_indices(subtrajectoriesABA)
        assert_equal(indicesA, [[0, 1], [3], [11, 12]])
        assert_equal(indicesB, [[5, 6], [8]])
        assert_equal(indicesABA, [[3, 4, 5, 6, 7, 8, 9, 10, 11]])
 def _tps_ensemble(self, stateA, stateB):
     return paths.SequentialEnsemble([
         paths.LengthEnsemble(1) & paths.AllInXEnsemble(stateA),
         paths.LengthEnsemble(self.length - 1) \
             & paths.PartInXEnsemble(stateB)
     ])