<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def run_vad( self, wave_energy, log_energy_threshold=None, min_nonspeech_length=None, extend_before=None, extend_after=None ):
 """ Compute the time intervals containing speech and nonspeech, and return a boolean mask with speech frames set to ``True``, and nonspeech frames set to ``False``. The last four parameters might be ``None``: in this case, the corresponding RuntimeConfiguration values are applied. :param wave_energy: the energy vector of the audio file (0-th MFCC) :type wave_energy: :class:`numpy.ndarray` (1D) :param float log_energy_threshold: the minimum log energy threshold to consider a frame as speech :param int min_nonspeech_length: the minimum length, in frames, of a nonspeech interval :param int extend_before: extend each speech interval by this number of frames to the left (before) :param int extend_after: extend each speech interval by this number of frames to the right (after) :rtype: :class:`numpy.ndarray` (1D) """

        self.log(u"Computing VAD for wave")
        mfcc_window_shift = self.rconf.mws
        self.log([u"MFCC window shift (s):         %.3f", mfcc_window_shift])
        if log_energy_threshold is None:
            log_energy_threshold = self.rconf[RuntimeConfiguration.VAD_LOG_ENERGY_THRESHOLD]
            self.log([u"Log energy threshold:          %.3f", log_energy_threshold])
        if min_nonspeech_length is None:
            min_nonspeech_length = int(self.rconf[RuntimeConfiguration.VAD_MIN_NONSPEECH_LENGTH] / mfcc_window_shift)
            self.log([u"Min nonspeech length (s):      %.3f", self.rconf[RuntimeConfiguration.VAD_MIN_NONSPEECH_LENGTH]])
        if extend_before is None:
            extend_before = int(self.rconf[RuntimeConfiguration.VAD_EXTEND_SPEECH_INTERVAL_BEFORE] / mfcc_window_shift)
            self.log([u"Extend speech before (s):      %.3f", self.rconf[RuntimeConfiguration.VAD_EXTEND_SPEECH_INTERVAL_BEFORE]])
        if extend_after is None:
            extend_after = int(self.rconf[RuntimeConfiguration.VAD_EXTEND_SPEECH_INTERVAL_AFTER] / mfcc_window_shift)
            self.log([u"Extend speech after (s):       %.3f", self.rconf[RuntimeConfiguration.VAD_EXTEND_SPEECH_INTERVAL_AFTER]])
        energy_length = len(wave_energy)
        energy_threshold = numpy.min(wave_energy) + log_energy_threshold
        self.log([u"Min nonspeech length (frames): %d", min_nonspeech_length])
        self.log([u"Extend speech before (frames): %d", extend_before])
        self.log([u"Extend speech after (frames):  %d", extend_after])
        self.log([u"Energy vector length (frames): %d", energy_length])
        self.log([u"Energy threshold (log):        %.3f", energy_threshold])

        # using windows to be sure we have at least
        # min_nonspeech_length consecutive frames with nonspeech
        self.log(u"Determining initial labels...")
        mask = wave_energy >= energy_threshold
        windows = self._rolling_window(mask, min_nonspeech_length)
        nonspeech_runs = self._compute_runs((numpy.where(numpy.sum(windows, axis=1) == 0))[0])
        self.log(u"Determining initial labels... done")

        # initially, everything is marked as speech
        # we remove the nonspeech intervals as needed,
        # possibly extending the adjacent speech interval
        # if requested by the user
        self.log(u"Determining final labels...")
        mask = numpy.ones(energy_length, dtype="bool")
        for ns in nonspeech_runs:
            start = ns[0]
            if (extend_after > 0) and (start > 0):
                start += extend_after
            stop = ns[-1] + min_nonspeech_length
            if (extend_before > 0) and (stop < energy_length - 1):
                stop -= extend_before
            mask[start:stop] = 0
        self.log(u"Determining final labels... done")
        return mask