docs: def filter_data(self, freq, FractionOfSampleFreq=1, PeakWidth=10000,
                      filterImplementation="filtfilt",
                      timeStart=None, timeEnd=None,
                      NPerSegmentPSD=1000000,
                      PyCUDA=False, MakeFig=True, show_fig=True):
          """
          filter out data about a central frequency with some bandwidth using an IIR filter.
      
          Parameters
          ----------
          freq : float
              The frequency of the peak of interest in the PSD
          FractionOfSampleFreq : integer, optional
              The fraction of the sample frequency to sub-sample the data by.
              This sometimes needs to be done because a filter with the appropriate
              frequency response may not be generated using the sample rate at which
              the data was taken. Increasing this number means the x, y and z signals
              produced by this function will be sampled at a lower rate but a higher
              number means a higher chance that the filter produced will have a nice
              frequency response.
          PeakWidth : float, optional
              The width of the pass-band of the IIR filter to be generated to
              filter the peak. Defaults to 10KHz
          filterImplementation : string, optional
              filtfilt or lfilter - use scipy.filtfilt or lfilter
              ifft - uses built in IFFT_filter
              default: filtfilt
          timeStart : float, optional
              Starting time for filtering. Defaults to start of time data.
          timeEnd : float, optional
              Ending time for filtering. Defaults to end of time data.
          NPerSegmentPSD : int, optional
              NPerSegment to pass to scipy.signal.welch to calculate the PSD
          PyCUDA : bool, optional
              Only important for the 'ifft'-method
              If True, uses PyCUDA to accelerate the FFT and IFFT
              via using your NVIDIA-GPU
              If False, performs FFT and IFFT with conventional
              scipy.fftpack
          MakeFig : bool, optional
              If True - generate figure showing filtered and unfiltered PSD
              Defaults to True.
          show_fig : bool, optional
              If True - plot unfiltered and filtered PSD
              Defaults to True.
      
          Returns
          -------
          timedata : ndarray
              Array containing the time data
          FiletedData : ndarray
              Array containing the filtered signal in volts with time.
          fig : matplotlib.figure.Figure object
              The figure object created showing the PSD of the filtered 
              and unfiltered signal
          ax : matplotlib.axes.Axes object
              The axes object created showing the PSD of the filtered 
              and unfiltered signal
          """
          if timeStart == None:
              timeStart = self.timeStart
          if timeEnd == None:
              timeEnd = self.timeEnd
  
          time = self.time.get_array()
  
          StartIndex = _np.where(time == take_closest(time, timeStart))[0][0]
          EndIndex = _np.where(time == take_closest(time, timeEnd))[0][0]
  
          
          input_signal = self.voltage[StartIndex: EndIndex][0::FractionOfSampleFreq]
          SAMPLEFREQ = self.SampleFreq / FractionOfSampleFreq
          if filterImplementation == "filtfilt" or filterImplementation == "lfilter":
              if filterImplementation == "filtfilt":
                  ApplyFilter = scipy.signal.filtfilt
              elif filterImplementation == "lfilter":
                  ApplyFilter = scipy.signal.lfilter
                  
      
              b, a = make_butterworth_bandpass_b_a(freq, PeakWidth, SAMPLEFREQ)
              print("filtering data")
              filteredData = ApplyFilter(b, a, input_signal)
      
              if(_np.isnan(filteredData).any()):
                  raise ValueError(
                      "Value Error: FractionOfSampleFreq must be higher, a sufficiently small sample frequency should be used to produce a working IIR filter.")
          elif filterImplementation == "ifft":
              filteredData = IFFT_filter(input_signal, SAMPLEFREQ, freq-PeakWidth/2, freq+PeakWidth/2, PyCUDA = PyCUDA)
          else:
              raise ValueError("filterImplementation must be one of [filtfilt, lfilter, ifft] you entered: {}".format(filterImplementation))
      
          if MakeFig == True:
              f, PSD = scipy.signal.welch(
                  input_signal, SAMPLEFREQ, nperseg=NPerSegmentPSD)
              f_filtdata, PSD_filtdata = scipy.signal.welch(filteredData, SAMPLEFREQ, nperseg=NPerSegmentPSD)
              fig, ax = _plt.subplots(figsize=properties["default_fig_size"])
              ax.plot(f, PSD)
              ax.plot(f_filtdata, PSD_filtdata, label="filtered data")
              ax.legend(loc="best")
              ax.semilogy()
              ax.set_xlim([freq - PeakWidth, freq + PeakWidth])
          else:
              fig = None
              ax = None
          if show_fig == True:
              _plt.show()
          timedata = time[StartIndex: EndIndex][0::FractionOfSampleFreq]
          return timedata, filteredData, fig, ax