Makes the ``Piper`` ready to return results. This involves starting the 
        the provided ``NuMap`` instance. If multiple ``Pipers`` share a 
        ``NuMap`` instance the order in which these ``Pipers`` are started is 
        important. The valid order is upstream before downstream. The ``NuMap`` 
        instance can only be started once, but the process can be done in 2 
        stages. This methods "stages" argument is a ``tuple`` which can contain
        any the numbers ``0`` and/or ``1`` and/or  ``2`` specifying which stage
        of the start routine should be carried out:
        
          - stage 0 - creates the needed ``itertools.tee`` objects.
          - stage 1 - activates ``NuMap`` pool. A call to ``next`` will block..
          - stage 2 - activates ``NuMap`` pool managers.
        
        If this ``Piper`` shares a ``NuMap`` with other ``Pipers`` the proper 
        way to start them is to start them in a valid postorder with stages 
        ``(0, 1)`` and ``(2,)`` separately. 
           
        Arguments:
        
          - stages(tuple) [default: ``(0,)`` if linear; ``(0,1,2)`` if parallel]
            Performs the specified stages of the start of a ``Piper`` instance. 
            Stage ``0`` is necessary and sufficient to start a linear ``Piper`` 
            which uses an ``itertools.imap``. Stages ``1`` and ``2`` are 
            required to start any parallel ``Piper`` instance.

def start(self, stages=None):
        """
        Makes the ``Piper`` ready to return results. This involves starting the 
        the provided ``NuMap`` instance. If multiple ``Pipers`` share a 
        ``NuMap`` instance the order in which these ``Pipers`` are started is 
        important. The valid order is upstream before downstream. The ``NuMap`` 
        instance can only be started once, but the process can be done in 2 
        stages. This methods "stages" argument is a ``tuple`` which can contain
        any the numbers ``0`` and/or ``1`` and/or  ``2`` specifying which stage
        of the start routine should be carried out:
        
          - stage 0 - creates the needed ``itertools.tee`` objects.
          - stage 1 - activates ``NuMap`` pool. A call to ``next`` will block..
          - stage 2 - activates ``NuMap`` pool managers.
        
        If this ``Piper`` shares a ``NuMap`` with other ``Pipers`` the proper 
        way to start them is to start them in a valid postorder with stages 
        ``(0, 1)`` and ``(2,)`` separately. 
           
        Arguments:
        
          - stages(tuple) [default: ``(0,)`` if linear; ``(0,1,2)`` if parallel]
            Performs the specified stages of the start of a ``Piper`` instance. 
            Stage ``0`` is necessary and sufficient to start a linear ``Piper`` 
            which uses an ``itertools.imap``. Stages ``1`` and ``2`` are 
            required to start any parallel ``Piper`` instance.
            
        """
        # defaults differ linear vs. parallel
        stages = stages or ((0,) if self.imap is imap else (0, 1, 2))
        if not self.connected:
            self.log.error('Piper %s is not connected.' % self)
            raise PiperError('Piper %s is not connected.' % self)

        if not self.started:
            if 0 in stages:
                self.tees.extend(tee(self, self.tee_num))

        if hasattr(self.imap, 'start'):
            # parallel piper
            self.imap.start(stages)
            if 2 in stages:
                self.log.debug('Piper %s has been started using %s' % \
                              (self, self.imap))
                self.started = True
        else:
            # linear piper
            self.log.debug('Piper %s has been started using %s' % \
                          (self, self.imap))
            self.started = True