def butter(dt_list, val, lowpass=1.0):
    """This is framework for a butterworth bandpass for 1D data
    
    Needs to be cleaned up and generalized
    """
    import scipy.signal
    import matplotlib.pyplot as plt
    #dt is 300 s, 5 min
    dt_diff = np.diff(dt_list)
    dt_diff = np.array([dt.total_seconds() for dt in dt_diff])
    dt = malib.fast_median(dt_diff)
    #f is 0.00333 Hz
    #288 samples/day
    fs = 1./dt
    nyq = fs/2.

    if False:
        #psd, f = psd(z_msl, fs) 
        sp_f, sp_psd = scipy.signal.periodogram(val, fs, detrend='linear')
        #sp_f, sp_psd = scipy.signal.welch(z_msl, fs, nperseg=2048)
        sp_f_days = 1./sp_f/86400.

        plt.figure()
        plt.plot(sp_f, sp_psd)
        plt.plot(sp_f_days, sp_psd)
        plt.semilogy(sp_f_days, sp_psd)
        plt.xlabel('Frequency')
        plt.ylabel('Power')

    print("Filtering tidal signal")
    #Define bandpass filter
    #f_min = dt/(86400*0.25)
    f_max = (1./(86400*0.1)) / nyq
    f_min = (1./(86400*1.8)) / nyq
    order = 6
    b, a = scipy.signal.butter(order, f_min, btype='highpass')
    #b, a = sp.signal.butter(order, (f_min, f_max), btype='bandpass')
    w, h = scipy.signal.freqz(b, a, worN=2000)
    w_f = (nyq/np.pi)*w
    w_f_days = 1/w_f/86400.
    #plt.figure()
    #plt.plot(w_f_days, np.abs(h))
    val_f_tide = scipy.signal.filtfilt(b, a, val)

    b, a = scipy.signal.butter(order, f_max, btype='lowpass')
    #b, a = sp.signal.butter(order, (f_min, f_max), btype='bandstop')
    w, h = scipy.signal.freqz(b, a, worN=2000)
    w_f = (nyq/np.pi)*w
    w_f_days = 1/w_f/86400.
    #plt.plot(w_f_days, np.abs(h))

    val_f_tide_denoise = scipy.signal.filtfilt(b, a, val_f_tide)
    #val_f_notide = sp.signal.filtfilt(b, a, val)
    val_f_notide = val - val_f_tide
This is framework for a butterworth bandpass for 1D data
    
    Needs to be cleaned up and generalized