<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def save_traj(traj_inp, indexes, outfile, top=None, stride = 1, chunksize=None, image_molecules=False, verbose=True):
 r""" Saves a sequence of frames as a single trajectory. Extracts the specified sequence of time/trajectory indexes from traj_inp and saves it to one single molecular dynamics trajectory file. The output format will be determined by the outfile name. Parameters traj_inp : traj_inp can be of two types. 1. a python list of strings containing the filenames associated with the indices in :py:obj:`indexes`. With this type of input, a :py:obj:`topfile` is mandatory. 2. a :py:func:`pyemma.coordinates.data.feature_reader.FeatureReader` object containing the filename list in :py:obj:`traj_inp.trajfiles`. Please use :py:func:`pyemma.coordinates.source` to construct it. With this type of input, the input :py:obj:`topfile` will be ignored. and :py:obj:`traj_inp.topfile` will be used instead indexes : ndarray(T, 2) or list of ndarray(T_i, 2) A (T x 2) array for writing a trajectory of T time steps. Each row contains two indexes (i, t), where i is the index of the trajectory from the input and t is the index of the time step within the trajectory. If a list of index arrays is given, these will be simply concatenated, i.e. they will be written subsequently in the same trajectory file. outfile : str. The name of the output file. Its extension will determine the file type written. Example: "out.dcd" If set to None, the trajectory object is returned to memory top : str, mdtraj.Trajectory, or mdtraj.Topology The topology needed to read the files in the list :py:obj:`traj_inp`. If :py:obj:`traj_inp` is not a list, this parameter is ignored. stride : integer, default is 1 This parameter informs :py:func:`save_traj` about the stride used in :py:obj:`indexes`. Typically, :py:obj:`indexes` contains frame-indexes that match exactly the frames of the files contained in :py:obj:`traj_inp.trajfiles`. However, in certain situations, that might not be the case. Examples are cases in which a stride value != 1 was used when reading/featurizing/transforming/discretizing the files contained in :py:obj:`traj_inp.trajfiles`. chunksize : int. Default=None. The chunksize for reading input trajectory files. If :py:obj:`traj_inp` is a :py:func:`pyemma.coordinates.data.feature_reader.FeatureReader` object, this input variable will be ignored and :py:obj:`traj_inp.chunksize` will be used instead. image_molecules: boolean, default is False If set to true, :py:obj:`save_traj` will call the method traj.image_molecules and try to correct for broken molecules accross periodic boundary conditions. (http://mdtraj.org/1.7.2/api/generated/mdtraj.Trajectory.html#mdtraj.Trajectory.image_molecules) verbose : boolean, default is True Inform about created filenames Returns ------- traj : :py:obj:`mdtraj.Trajectory` object Will only return this object if :py:obj:`outfile` is None """

    from mdtraj import Topology, Trajectory

    from pyemma.coordinates.data.feature_reader import FeatureReader
    from pyemma.coordinates.data.fragmented_trajectory_reader import FragmentedTrajectoryReader
    from pyemma.coordinates.data.util.frames_from_file import frames_from_files
    from pyemma.coordinates.data.util.reader_utils import enforce_top
    import itertools

    # Determine the type of input and extract necessary parameters
    if isinstance(traj_inp, (FeatureReader, FragmentedTrajectoryReader)):
        if isinstance(traj_inp, FragmentedTrajectoryReader):
            # lengths array per reader
            if not all(isinstance(reader, FeatureReader)
                                     for reader in itertools.chain.from_iterable(traj_inp._readers)):
                raise ValueError("Only FeatureReaders (MD-data) are supported for fragmented trajectories.")
            trajfiles = traj_inp.filenames_flat
            top = traj_inp._readers[0][0].featurizer.topology
        else:
            top = traj_inp.featurizer.topology
            trajfiles = traj_inp.filenames
        chunksize = traj_inp.chunksize
        reader = traj_inp
    else:
        # Do we have what we need?
        if not isinstance(traj_inp, (list, tuple)):
            raise TypeError("traj_inp has to be of type list, not %s" % type(traj_inp))
        if not isinstance(top, (_string_types, Topology, Trajectory)):
            raise TypeError("traj_inp cannot be a list of files without an input "
                            "top of type str (eg filename.pdb), mdtraj.Trajectory or mdtraj.Topology. "
                            "Got type %s instead" % type(top))
        trajfiles = traj_inp
        reader = None

    # Enforce the input topology to actually be an md.Topology object
    top = enforce_top(top)

    # Convert to index (T,2) array if parsed a list or a list of arrays
    indexes = _np.vstack(indexes)

    # Check that we've been given enough filenames
    if len(trajfiles) < indexes[:, 0].max():
        raise ValueError("traj_inp contains %u trajfiles, "
                         "but indexes will ask for file nr. %u"
                         % (len(trajfiles), indexes[:,0].max()))

    traj = frames_from_files(trajfiles, top, indexes, chunksize, stride, reader=reader)

    # Avoid broken molecules
    if image_molecules:
        traj.image_molecules(inplace=True)

    # Return to memory as an mdtraj trajectory object
    if outfile is None:
        return traj
    # or to disk as a molecular trajectory file
    else:
        traj.save(outfile)
    if verbose:
        _logger.info("Created file %s" % outfile)