def stop(self, forced=False, **kwargs):
<EOL>if not self.started:<EOL><INDENT>self.log.error('<STR_LIT>' % self)<EOL>raise PiperError('<STR_LIT>' % self)<EOL><DEDENT>elif not self.finished and not forced:<EOL><INDENT>msg = '<STR_LIT>' % self<EOL>self.log.error(msg)<EOL>raise PiperError(msg)<EOL><DEDENT>else:<EOL><INDENT>if hasattr(self.imap, '<STR_LIT>'):<EOL><INDENT>self.imap.stop(forced=forced, **kwargs)<EOL><DEDENT>self.started = False<EOL>self.log.debug('<STR_LIT>' %(self, self.finished))<EOL><DEDENT>
Attempts to cleanly stop the ``Piper`` instance. A ``Piper`` is 
"started" if its  ``NuMap`` instance is "started". Non-parallel 
``Pipers`` do not have to be started or stopped. An ``NuMap`` instance
can be stopped by triggering its stopping procedure and retrieving 
results from the ``NuMaps`` end tasks. Because neither the ``Piper`` nor
the ``NuMap`` "knows" which tasks i.e. ``Pipers`` are the end tasks 
they have to be specified::

    end_task_ids = [0, 1]    # A list of NuMap task ids
    piper_instance.stop(ends =end_task_ids)        

results in::

    NuMap_instance.stop(ends =[0,1])

If the ``Piper`` did not finish processing the data before the 
stop method is called the "forced" argument has to be ``True``::

    piper_instance.stop(forced =True, ends =end_task_ids)

If the ``Piper`` (and consequently ``NuMap``) is part of a ``Dagger`` 
graph the ``Dagger.stop`` method should be called instead. See: 
``NuMap.stop`` and ``Dagger.stop``.

# verify this:
# If "forced" is set ``True`` but the ends ``NuMap`` argument is not
# given. The ``NuMap`` instance will not try to retrieve any results and
# will not call the ``NuMap._stop`` method.

Arguments:

  - forced(``bool``) [default: ``False``] The ``Piper`` will be forced 
    to stop the ``NuMap`` instance.

Additional keyworded arguments are passed to the ``Piper.imap`` 
instance.