docs: function catheter(pw, lfn, it, passes, pass, args) {
      var iv = [];
      iv.listen = lfn;
      iv.target = it || pw;
      iv.dripCount = 0;
      iv.count = 1;
      iv.meds = [];
      iv.hasEnd = false;
      iv.ended = false;
      iv.emitted = [];
      iv.drained = [];
      iv.artery = null;
      iv.data = [];
      iv.passes = passes && typeof passes === 'object' ? passes : {};
      iv.pass = pass && Array.isArray(pass) ? pass : [];
      iv.passing = iv.pass.slice();
      iv.args = args && Array.isArray(args) ? args : null;
      
      /**
       * Pumps pulse events (aka meds) through the pulse emitter
       * 
       * @see {@link PulseEmitter#pump}
       * @arg {(Array | Object)} meds the pulse events
       * @arg {Boolean} begin true to begin emission
       * @returns {Array} the I.V. array
       */
      iv.pump = function pump(meds, begin) {
          if (iv.length) return iv.drain();
          plet.merge(iv, artery(pw, iv, meds), true);
          meds = Array.isArray(meds) ? meds : meds.events;
          for (var i = 0, l = meds.length; i < l; i++) {
              if (valve(pw, iv, meds[i]).pulse.event === pw.options.endEvent) {
                  iv.drain(null, true);
                  throw new TypeError('Explicit declaration of "' + pw.options.endEvent + '" event detected at index ' + i);
              }
          }
          if (iv.length) {
              valve(pw, iv, pw.options.endEvent);
              if (begin) emits(pw, iv, 0);
          }
          return iv;
      };
      
      /**
       * Drains pending pulse events from being emitted (will not drain currently running async events)
       * Subsequently, continues pumping any remaining pulse events left in the artery once it's drained  
       * 
       * @arg {Object} [drip=iv] the drip created during a pump that contains pulse event details
       *        (omit will drain all pending pulse events except for async pulses)
       * @arg {Boolean} [exit] true to prevent continuation of event drainage after listeners have been removed (must also omit drip)
       */
      iv.drain = function drain(drip, exit) {
          var drips = iv, isEnd = false, isLast = false;
          if (drip) {
              drip.cbCount++;
              drips = (isEnd = drip.pulse.event === pw.options.endEvent) ? iv : drip.cbCount < drip.pulse.repeat ? [] : [drip];
              iv.drained.push(drip.pulse.event);
              iv.count += isEnd ? 1 : 0;
          }
          var l = drips.length;
          if (l) {
              for (var i = 0; i < l; i++) pw.removeListener(drips[i].pulse.event, drips[i].callback);
              drips.length = 0;
          }
          if (!drip && exit) return;
          isLast = iv.drained.length >= iv.dripCount;
          if (!isEnd && isLast) {
              if (iv.count < iv.repeat) { // rinse/repeat
                  iv.count++;
                  for (var i = iv.length = 0, l = iv.meds.length; i < l; i++) valve(pw, iv, iv.meds[i]);
                  emits(pw, iv, 0);
              } else if (!iv.ended) { // ensure end event is emitted
                  iv.ended = true;
                  new Drip(pw, iv, pw.options.endEvent, pw.options.endEvent, true);
              }
          } else if (!isLast) { // start emitting next queued pulse event(s)
              for (var ci = iv.indexOf(drip), i = ci, x = -1; iv[i]; i += x) {
                  //console.dir({ iv: iv[i], i: i, x: x, ci: ci });
                  if (iv[i].cbCount < iv[i].pulse.repeat) return iv[i].emit(pw, iv); // start emitting next in line
                  else if (i === 0 && x < 0) { // look at next emmited event
                      i = ci;
                      x = 1;
                  }
              }
          }
      };
      
      return iv;
  }