def piter(self, storage=None, dynamic=False):
    'Iterate over time series components in parallel.\n\n        This allows you to iterate over a time series while dispatching\n        individual components of that time series to different processors or\n        processor groups.  If the parallelism strategy was set to be\n        multi-processor (by "parallel = N" where N is an integer when the\n        DatasetSeries was created) this will issue each dataset to an\n        N-processor group.  For instance, this would allow you to start a 1024\n        processor job, loading up 100 datasets in a time series and creating 8\n        processor groups of 128 processors each, each of which would be\n        assigned a different dataset.  This could be accomplished as shown in\n        the examples below.  The *storage* option is as seen in\n        :func:`~yt.utilities.parallel_tools.parallel_analysis_interface.parallel_objects`\n        which is a mechanism for storing results of analysis on an individual\n        dataset and then combining the results at the end, so that the entire\n        set of processors have access to those results.\n\n        Note that supplying a *store* changes the iteration mechanism; see\n        below.\n\n        Parameters\n        ----------\n        storage : dict\n            This is a dictionary, which will be filled with results during the\n            course of the iteration.  The keys will be the dataset\n            indices and the values will be whatever is assigned to the *result*\n            attribute on the storage during iteration.\n        dynamic : boolean\n            This governs whether or not dynamic load balancing will be\n            enabled.  This requires one dedicated processor; if this\n            is enabled with a set of 128 processors available, only\n            127 will be available to iterate over objects as one will\n            be load balancing the rest.\n\n\n        Examples\n        --------\n        Here is an example of iteration when the results do not need to be\n        stored.  One processor will be assigned to each dataset.\n\n        >>> ts = DatasetSeries("DD*/DD*.index")\n        >>> for ds in ts.piter():\n        ...    SlicePlot(ds, "x", "Density").save()\n        ...\n        \n        This demonstrates how one might store results:\n\n        >>> def print_time(ds):\n        ...     print ds.current_time\n        ...\n        >>> ts = DatasetSeries("DD*/DD*.index",\n        ...             setup_function = print_time )\n        ...\n        >>> my_storage = {}\n        >>> for sto, ds in ts.piter(storage=my_storage):\n        ...     v, c = ds.find_max("density")\n        ...     sto.result = (v, c)\n        ...\n        >>> for i, (v, c) in sorted(my_storage.items()):\n        ...     print "% 4i  %0.3e" % (i, v)\n        ...\n\n        This shows how to dispatch 4 processors to each dataset:\n\n        >>> ts = DatasetSeries("DD*/DD*.index",\n        ...                     parallel = 4)\n        >>> for ds in ts.piter():\n        ...     ProjectionPlot(ds, "x", "Density").save()\n        ...\n\n        '
    if (self.parallel is False):
        njobs = 1
    elif (dynamic is False):
        if (self.parallel is True):
            njobs = (- 1)
        else:
            njobs = self.parallel
    else:
        my_communicator = communication_system.communicators[(- 1)]
        nsize = my_communicator.size
        if (nsize == 1):
            self.parallel = False
            dynamic = False
            njobs = 1
        else:
            njobs = (nsize - 1)
    for output in parallel_objects(self._pre_outputs, njobs=njobs, storage=storage, dynamic=dynamic):
        if (storage is not None):
            (sto, output) = output
        if isinstance(output, string_types):
            ds = self._load(output, **self.kwargs)
            self._setup_function(ds)
        else:
            ds = output
        if (storage is not None):
            next_ret = (sto, ds)
        else:
            next_ret = ds
        (yield next_ret)
Iterate over time series components in parallel.

This allows you to iterate over a time series while dispatching
individual components of that time series to different processors or
processor groups.  If the parallelism strategy was set to be
multi-processor (by "parallel = N" where N is an integer when the
DatasetSeries was created) this will issue each dataset to an
N-processor group.  For instance, this would allow you to start a 1024
processor job, loading up 100 datasets in a time series and creating 8
processor groups of 128 processors each, each of which would be
assigned a different dataset.  This could be accomplished as shown in
the examples below.  The *storage* option is as seen in
:func:`~yt.utilities.parallel_tools.parallel_analysis_interface.parallel_objects`
which is a mechanism for storing results of analysis on an individual
dataset and then combining the results at the end, so that the entire
set of processors have access to those results.

Note that supplying a *store* changes the iteration mechanism; see
below.

Parameters
----------
storage : dict
    This is a dictionary, which will be filled with results during the
    course of the iteration.  The keys will be the dataset
    indices and the values will be whatever is assigned to the *result*
    attribute on the storage during iteration.
dynamic : boolean
    This governs whether or not dynamic load balancing will be
    enabled.  This requires one dedicated processor; if this
    is enabled with a set of 128 processors available, only
    127 will be available to iterate over objects as one will
    be load balancing the rest.


Examples
--------
Here is an example of iteration when the results do not need to be
stored.  One processor will be assigned to each dataset.

>>> ts = DatasetSeries("DD*/DD*.index")
>>> for ds in ts.piter():
...    SlicePlot(ds, "x", "Density").save()
...

This demonstrates how one might store results:

>>> def print_time(ds):
...     print ds.current_time
...
>>> ts = DatasetSeries("DD*/DD*.index",
...             setup_function = print_time )
...
>>> my_storage = {}
>>> for sto, ds in ts.piter(storage=my_storage):
...     v, c = ds.find_max("density")
...     sto.result = (v, c)
...
>>> for i, (v, c) in sorted(my_storage.items()):
...     print "% 4i  %0.3e" % (i, v)
...

This shows how to dispatch 4 processors to each dataset:

>>> ts = DatasetSeries("DD*/DD*.index",
...                     parallel = 4)
>>> for ds in ts.piter():
...     ProjectionPlot(ds, "x", "Density").save()
...
def piter(self, storage=None, dynamic=False):
    'Iterate over time series components in parallel.\n\n        This allows you to iterate over a time series while dispatching\n        individual components of that time series to different processors or\n        processor groups.  If the parallelism strategy was set to be\n        multi-processor (by "parallel = N" where N is an integer when the\n        DatasetSeries was created) this will issue each dataset to an\n        N-processor group.  For instance, this would allow you to start a 1024\n        processor job, loading up 100 datasets in a time series and creating 8\n        processor groups of 128 processors each, each of which would be\n        assigned a different dataset.  This could be accomplished as shown in\n        the examples below.  The *storage* option is as seen in\n        :func:`~yt.utilities.parallel_tools.parallel_analysis_interface.parallel_objects`\n        which is a mechanism for storing results of analysis on an individual\n        dataset and then combining the results at the end, so that the entire\n        set of processors have access to those results.\n\n        Note that supplying a *store* changes the iteration mechanism; see\n        below.\n\n        Parameters\n        ----------\n        storage : dict\n            This is a dictionary, which will be filled with results during the\n            course of the iteration.  The keys will be the dataset\n            indices and the values will be whatever is assigned to the *result*\n            attribute on the storage during iteration.\n        dynamic : boolean\n            This governs whether or not dynamic load balancing will be\n            enabled.  This requires one dedicated processor; if this\n            is enabled with a set of 128 processors available, only\n            127 will be available to iterate over objects as one will\n            be load balancing the rest.\n\n\n        Examples\n        --------\n        Here is an example of iteration when the results do not need to be\n        stored.  One processor will be assigned to each dataset.\n\n        >>> ts = DatasetSeries("DD*/DD*.index")\n        >>> for ds in ts.piter():\n        ...    SlicePlot(ds, "x", "Density").save()\n        ...\n        \n        This demonstrates how one might store results:\n\n        >>> def print_time(ds):\n        ...     print ds.current_time\n        ...\n        >>> ts = DatasetSeries("DD*/DD*.index",\n        ...             setup_function = print_time )\n        ...\n        >>> my_storage = {}\n        >>> for sto, ds in ts.piter(storage=my_storage):\n        ...     v, c = ds.find_max("density")\n        ...     sto.result = (v, c)\n        ...\n        >>> for i, (v, c) in sorted(my_storage.items()):\n        ...     print "% 4i  %0.3e" % (i, v)\n        ...\n\n        This shows how to dispatch 4 processors to each dataset:\n\n        >>> ts = DatasetSeries("DD*/DD*.index",\n        ...                     parallel = 4)\n        >>> for ds in ts.piter():\n        ...     ProjectionPlot(ds, "x", "Density").save()\n        ...\n\n        '
    if (self.parallel is False):
        njobs = 1
    elif (dynamic is False):
        if (self.parallel is True):
            njobs = (- 1)
        else:
            njobs = self.parallel
    else:
        my_communicator = communication_system.communicators[(- 1)]
        nsize = my_communicator.size
        if (nsize == 1):
            self.parallel = False
            dynamic = False
            njobs = 1
        else:
            njobs = (nsize - 1)
    for output in parallel_objects(self._pre_outputs, njobs=njobs, storage=storage, dynamic=dynamic):
        if (storage is not None):
            (sto, output) = output
        if isinstance(output, string_types):
            ds = self._load(output, **self.kwargs)
            self._setup_function(ds)
        else:
            ds = output
        if (storage is not None):
            next_ret = (sto, ds)
        else:
            next_ret = ds
        (yield next_ret)