<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def median_filter(tr, multiplier=10, windowlength=0.5, interp_len=0.05, debug=0):
 """ Filter out spikes in data above a multiple of MAD of the data. Currently only has the ability to replaces spikes with linear interpolation. In the future we would aim to fill the gap with something more appropriate. Works in-place on data. :type tr: obspy.core.trace.Trace :param tr: trace to despike :type multiplier: float :param multiplier: median absolute deviation multiplier to find spikes above. :type windowlength: float :param windowlength: Length of window to look for spikes in in seconds. :type interp_len: float :param interp_len: Length in seconds to interpolate around spikes. :type debug: int :param debug: Debug output level between 0 and 5, higher is more output. :returns: :class:`obspy.core.trace.Trace` .. warning:: Not particularly effective, and may remove earthquake signals, use with caution. """

    num_cores = cpu_count()
    if debug >= 1:
        data_in = tr.copy()
    # Note - might be worth finding spikes in filtered data
    filt = tr.copy()
    filt.detrend('linear')
    try:
        filt.filter('bandpass', freqmin=10.0,
                    freqmax=(tr.stats.sampling_rate / 2) - 1)
    except Exception as e:
        print("Could not filter due to error: {0}".format(e))
    data = filt.data
    del filt
    # Loop through windows
    _windowlength = int(windowlength * tr.stats.sampling_rate)
    _interp_len = int(interp_len * tr.stats.sampling_rate)
    peaks = []
    with Timer() as t:
        pool = Pool(processes=num_cores)
        results = [pool.apply_async(_median_window,
                                    args=(data[chunk * _windowlength:
                                               (chunk + 1) * _windowlength],
                                          chunk * _windowlength, multiplier,
                                          tr.stats.starttime + windowlength,
                                          tr.stats.sampling_rate,
                                          debug))
                   for chunk in range(int(len(data) / _windowlength))]
        pool.close()
        for p in results:
            peaks += p.get()
        pool.join()
        for peak in peaks:
            tr.data = _interp_gap(tr.data, peak[1], _interp_len)
    print("Despiking took: %s s" % t.secs)
    if debug >= 1:
        plt.plot(data_in.data, 'r', label='raw')
        plt.plot(tr.data, 'k', label='despiked')
        plt.legend()
        plt.show()
    return tr