<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _add_halfwave(data, events, s_freq, opts):
 """Find the next zero crossing and the intervening peak and add them to events. If no zero found before max_dur, event is discarded. If peak-to-peak is smaller than min_ptp, the event is discarded. Parameters data : ndarray (dtype='float') vector with the data events : ndarray (dtype='int') N x 3 matrix with start, trough, end samples s_freq : float sampling frequency opts : instance of 'DetectSlowWave' 'duration' : tuple of float min and max duration of SW 'min_ptp' : float min peak-to-peak amplitude Returns ------- ndarray (dtype='int') N x 5 matrix with start, trough, - to + zero crossing, peak, and end samples """

    max_dur = opts.duration[1]
    if max_dur is None:
        max_dur = MAXIMUM_DURATION
    
    window = int(s_freq * max_dur)

    peak_and_end = zeros((events.shape[0], 2), dtype='int')
    events = concatenate((events, peak_and_end), axis=1)
    selected = []

    for ev in events:
        zero_crossings = where(diff(sign(data[ev[2]:ev[0] + window])))[0]
        
        if zero_crossings.any():
            ev[4] = ev[2] + zero_crossings[0] + 1
            #lg.info('0cross is at ' + str(ev[4]))
            
        else:
            selected.append(False)
            #lg.info('no 0cross, rejected')
            continue

        ev[3] = ev[2] + argmin(data[ev[2]:ev[4]])

        if abs(data[ev[1]] - data[ev[3]]) < opts.min_ptp:
            selected.append(False)
            #lg.info('ptp too low, rejected: ' + str(abs(data[ev[1]] - data[ev[3]])))
            continue

        selected.append(True)
        #lg.info('SW checks out, accepted! ptp is ' + str(abs(data[ev[1]] - data[ev[3]])))

    return events[selected, :]