Ejemplo n.º 1
0
 def plot_L0_Pstar(self, axes=None, label=None, FIGSIZE=None):
     if axes is None:
         figure, axes = plt.subplots(1, figsize=FIGSIZE)
     color = next(axes._get_lines.prop_cycler)['color']
     axes.plot(np.arange(self.Nfreqs) + 1,
               self.dct.logtau,
               '.-',
               c=color,
               label=label)
     axes.plot(np.arange(self.Nfreqs) + 1,
               self.dct.logtau + self.dct.logtau_THEORY_std,
               '--',
               c=color)
     axes.plot(np.arange(self.Nfreqs) + 1,
               self.dct.logtau - self.dct.logtau_THEORY_std,
               '--',
               c=color)
     axes.axvline(x=self.dct.aic_Kmin + 1, ls='--', c=color)
     axes.set_xlim([0, 3 * self.dct.aic_Kmin])
     max_y = np.amax((self.dct.logtau +
                      self.dct.logtau_THEORY_std)[self.dct.aic_Kmin:3 *
                                                  self.dct.aic_Kmin])
     min_y = np.amin((self.dct.logtau -
                      self.dct.logtau_THEORY_std)[self.dct.aic_Kmin:3 *
                                                  self.dct.aic_Kmin])
     axes.set_ylim([min_y * 0.8, max_y * 1.2])
     axes.set_xlabel(r'$P^*$')
     axes.set_ylabel(r'$L_0(P*)$')
     return axes
Ejemplo n.º 2
0
 def plot_kappa_Pstar(self, axes=None, label=None, FIGSIZE=None):
     if axes is None:
         figure, axes = plt.subplots(1, figsize=FIGSIZE)
     color = next(axes._get_lines.prop_cycler)['color']
     axes.plot(np.arange(self.Nfreqs) + 1,
               self.dct.tau * self.kappa_scale * 0.5,
               '.-',
               c=color,
               label=label)
     axes.plot(np.arange(self.Nfreqs) + 1, (self.dct.tau + self.dct.tau_THEORY_std) * self.kappa_scale * 0.5,
               '--', c=color)   # yapf: disable
     axes.plot(np.arange(self.Nfreqs) + 1, (self.dct.tau - self.dct.tau_THEORY_std) * self.kappa_scale * 0.5,
               '--', c=color)   # yapf: disable
     axes.axvline(x=self.dct.aic_Kmin + 1, ls='--', c=color)
     axes.axhline(y=self.kappa_Kmin, ls='--', c=color)
     axes.set_xlim([0, 3 * self.dct.aic_Kmin])
     max_y = np.amax(
         self.kappa_scale * 0.5 *
         (self.dct.tau + self.dct.tau_THEORY_std)[self.dct.aic_Kmin:3 *
                                                  self.dct.aic_Kmin])
     min_y = np.amin(
         self.kappa_scale * 0.5 *
         (self.dct.tau - self.dct.tau_THEORY_std)[self.dct.aic_Kmin:3 *
                                                  self.dct.aic_Kmin])
     axes.set_ylim([min_y * 0.8, max_y * 1.2])
     axes.set_xlabel(r'$P^*$')
     axes.set_ylabel(r'$\kappa(P^*)$ [W/(m*K)]')
     return axes
Ejemplo n.º 3
0
 def plot_ck(self, axes=None, label=None, FIGSIZE=None):
     if axes is None:
         figure, axes = plt.subplots(1, figsize=FIGSIZE)
     color = next(axes._get_lines.prop_cycler)['color']
     axes.plot(self.dct.logpsdK, 'o-', c=color, label=label)
     axes.plot(self.dct.logpsdK + self.dct.logpsdK_THEORY_std,
               '--',
               c=color)
     axes.plot(self.dct.logpsdK - self.dct.logpsdK_THEORY_std,
               '--',
               c=color)
     axes.axvline(x=self.dct.aic_Kmin, ls='--', c=color)
     axes.set_xlabel(r'$k$')
     axes.set_ylabel(r'$c_k$')
     return axes
Ejemplo n.º 4
0
 def plot_cepstral_spectrum(self,
                            freq_units='thz',
                            freq_scale=1.0,
                            axes=None,
                            kappa_units=True,
                            FIGSIZE=None,
                            **plot_kwargs):
     if axes is None:
         figure, axes = plt.subplots(2, sharex=True, figsize=FIGSIZE)
     plt.subplots_adjust(hspace=0.1)
     if kappa_units:
         psd_scale = 0.5 * self.kappa_scale
     else:
         psd_scale = 1.0
     if (freq_units == 'thz') or (freq_units == 'THz'):
         axes[0].plot(self.freqs_THz, self.dct.psd * psd_scale,
                      **plot_kwargs)
         axes[1].plot(self.freqs_THz, self.dct.logpsd, **plot_kwargs)
         axes[0].set_xlim([0., self.Nyquist_f_THz])
         axes[1].set_xlim([0., self.Nyquist_f_THz])
     elif (freq_units == 'red'):
         axes[0].plot(self.freqs / freq_scale, self.dct.psd * psd_scale,
                      **plot_kwargs)
         axes[1].plot(self.freqs / freq_scale, self.dct.logpsd,
                      **plot_kwargs)
         axes[0].set_xlim([0., 0.5 / freq_scale])
         axes[1].set_xlim([0., 0.5 / freq_scale])
     else:
         raise ValueError('Units not valid.')
     axes[0].xaxis.set_ticks_position('top')
     axes[0].set_ylabel(r'PSD')
     if kappa_units:
         axes[0].set_ylabel(r'PSD [W/mK]')
     else:
         axes[0].set_ylabel(r'PSD')
     axes[0].grid()
     axes[1].xaxis.set_ticks_position('bottom')
     axes[1].set_xlabel(r'$f$ [THz]')
     axes[1].set_ylabel(r'log(PSD)')
     axes[1].grid()
     return axes
Ejemplo n.º 5
0
def fstar_analysis(x, TSKIP_LIST, aic_type='aic', Kmin_corrfactor=1.0, plot=True, axes=None, FIGSIZE=None,
                   verbose=False, **plot_kwargs):   # yapf: disable
    """
    Perform cepstral analysis on a set of resampled time series, to study the effect of f*.
    For each TSKIP in TSKIP_LIST, the HeatCurrent x is filtered & resampled, and then cesptral-analysed.

    Parameters
    ----------
    TSKIP_LIST    = list of sampling times [steps]
    aic_type      = the Akaike Information Criterion function used to choose the cutoff ('aic', 'aicc')
    Kmin_corrfactor = correction factor multiplied by the AIC cutoff (cutoff = Kmin_corrfactor * aic_Kmin)
    plot          = plot the PSD (True/False)
    axes          = matplotlib.axes.Axes object (if None, create one)
    FIGSIZE       = plot figure size
    verbose       = verbose output (default: False)
    **plot_kwargs = other parameters passed to plot function

    Returns
    -------
    xf : array_like
        an array of HeatCurrents, corresponding the values of TSKIP_LIST
    ax : array_like, optional (if plot=True)
        array of plot axes
    fig : figure, optional (if axes=None)
        plot figure
    """

    if not isinstance(x, HeatCurrent):
        raise ValueError('x must be a HeatCurrent object.')

    xf = []
    for TSKIP in TSKIP_LIST:
        log.write_log('TSKIP =  {:d}'.format(TSKIP))
        xff = resample_current(x, TSKIP, plot=False, verbose=verbose)
        xff.cepstral_analysis(aic_type, Kmin_corrfactor)
        xf.append(xff)
    FSTAR_THZ_LIST = [xff.Nyquist_f_THz for xff in xf]

    if plot:
        if axes is None:
            figure, ax = plt.subplots(2, sharex=True, figsize=FIGSIZE)
        else:
            ax = axes
        ax[0].errorbar(FSTAR_THZ_LIST, [xff.kappa_Kmin for xff in xf],
                       yerr=[xff.kappa_Kmin_std for xff in xf],
                       **plot_kwargs)
        ax[1].errorbar(FSTAR_THZ_LIST, [xff.dct.logtau_Kmin for xff in xf],
                       yerr=[xff.dct.logtau_std_Kmin for xff in xf],
                       **plot_kwargs)
        # ax[0].plot(x.freqs_THz, x.fpsd,    **plot_kwargs)
        # ax[1].plot(x.freqs_THz, x.flogpsd, **plot_kwargs)
        ax[0].xaxis.set_ticks_position('top')
        ax[0].set_ylabel(r'PSD')
        ax[0].grid()
        ax[1].xaxis.set_ticks_position('bottom')
        ax[1].set_xlabel(r'$f$ [THz]')
        ax[1].set_ylabel(r'log(PSD)')
        ax[1].grid()

        if axes is None:
            ax2 = [ax[0].twinx(), ax[1].twinx()]
            color = next(ax[0]._get_lines.prop_cycler)['color']
            color = next(ax[1]._get_lines.prop_cycler)['color']
            x.plot_periodogram(axes=ax2, c=color)
            ax[0].set_ylabel(r'$\kappa$ [W/(m*K)]')
            ax[1].set_ylabel(r'$\kappa$ [W/(m*K)]')
            return xf, ax, figure
        else:
            return xf, ax
    else:
        return xf
Ejemplo n.º 6
0
def resample_current(x, TSKIP=None, fstar_THz=None, FILTER_W=None, plot=True, PSD_FILTER_W=None, freq_units='thz',
                     FIGSIZE=None, verbose=True):   # yapf: disable
    """
    Simulate the resampling of x.

    Parameters
    ----------
    TSKIP        = sampling time [steps]
    fstar_THz    = target cutoff frequency [THz]
    FILTER_W     = pre-sampling filter window width [steps]
    plot         = plot the PSD (True/False)
    PSD_FILTER_W = PSD filtering window width [chosen frequency units]
    freq_units   = 'thz'  THz
                   'red'  omega*DT/(2*pi)
    FIGSIZE      = plot figure size

    Returns
    -------
    xf : HeatCurrent object
        a filtered & resampled HeatCurrent
    ax : array_like, optional (if plot=True)
        an array of plot axes
    """

    if not isinstance(x, HeatCurrent):
        raise ValueError('x must be a HeatCurrent object.')
    if (TSKIP is not None) and (fstar_THz is not None):
        raise ValueError('Please specify either TSKIP or fstar_THz.')
    if TSKIP is None:
        if fstar_THz is None:
            raise ValueError('Please specify either TSKIP or fstar_THz.')
        else:
            TSKIP = int(round(x.Nyquist_f_THz / fstar_THz))
    if plot:
        figure, axes = plt.subplots(2, sharex=True, figsize=FIGSIZE)
        axes = x.plot_periodogram(
            PSD_FILTER_W, freq_units, 1.0,
            axes=axes)  # this also updates x.FILTER_WINDOW_WIDTH

    fstar_THz = x.Nyquist_f_THz / TSKIP
    fstar_idx = np.argmin(x.freqs_THz < fstar_THz)

    # filter and sample
    if FILTER_W is None:
        FILTER_W = TSKIP
    trajf = md.tools.filter_and_sample(x.traj, FILTER_W, TSKIP, 'rectangular')

    #TODO: document the units of frequency used everywere in the library and use a consistent scheme.

    # resample filtering window width in order to use the same filtering frequency window in the plot
    # if PSD_FILTER_W was specified, then x.FILTER_WINDOW_WIDTH was updated by the previous plot function
    #if x.FILTER_WINDOW_WIDTH is not None:
    #    PSD_FILTER_W = x.FILTER_WINDOW_WIDTH * TSKIP

    # define new HeatCurrent
    if not x.many_currents:
        xf = HeatCurrent(trajf, x.units, x.DT_FS * TSKIP, x.TEMPERATURE,
                         x.VOLUME, PSD_FILTER_W, freq_units)
    else:
        if x.otherMD is None:
            raise RuntimeError(
                'x.otherMD cannot be none (wrong/missing initialization?)')
        # filter_and_sample also other trajectories
        yf = []
        yf.append(trajf)
        for y in x.otherMD:
            tmp = md.tools.filter_and_sample(y.traj, FILTER_W, TSKIP,
                                             'rectangular')
            yf.append(tmp)
        xf = HeatCurrent(yf, x.units, x.DT_FS * TSKIP, x.TEMPERATURE, x.VOLUME,
                         PSD_FILTER_W, freq_units)
    if plot:
        if (freq_units == 'thz') or (freq_units == 'THz'):
            xf.plot_periodogram(x.FILTER_WINDOW_WIDTH * 1000. / x.DT_FS,
                                'thz',
                                TSKIP,
                                axes=axes)
        elif (freq_units == 'red'):
            log.write_log(PSD_FILTER_W)
            log.write_log(x.FILTER_WINDOW_WIDTH)
            xf.plot_periodogram(x.FILTER_WINDOW_WIDTH * TSKIP,
                                'red',
                                TSKIP,
                                axes=axes)

    # write log
    xf.resample_log = \
        '-----------------------------------------------------\n' +\
        '  RESAMPLE TIME SERIES\n' +\
        '-----------------------------------------------------\n' +\
        ' Original Nyquist freq  f_Ny =  {:12.5f} THz\n'.format(x.Nyquist_f_THz) +\
        ' Resampling freq          f* =  {:12.5f} THz\n'.format(fstar_THz) +\
        ' Sampling time         TSKIP =  {:12d} steps\n'.format(TSKIP) +\
        '                             =  {:12.3f} fs\n'.format(TSKIP * x.DT_FS) +\
        ' Original  n. of frequencies =  {:12d}\n'.format(x.Nfreqs) +\
        ' Resampled n. of frequencies =  {:12d}\n'.format(xf.Nfreqs)
    if x.fpsd is not None and xf.fpsd is not None:
        xf.resample_log += \
            ' PSD      @cutoff  (pre-filter) = {:12.5f}\n'.format(x.fpsd[fstar_idx]) +\
            '                  (post-filter) = {:12.5f}\n'.format(xf.fpsd[-1]) +\
            ' log(PSD) @cutoff  (pre-filter) = {:12.5f}\n'.format(x.flogpsd[fstar_idx]) +\
            '                  (post-filter) = {:12.5f}\n'.format(xf.flogpsd[-1]) +\
            ' min(PSD)          (pre-filter) = {:12.5f}\n'.format(x.psd_min) +\
            ' min(PSD)         (post-filter) = {:12.5f}\n'.format(xf.psd_min) +\
            ' % of original PSD Power f<f* (pre-filter)  = {:5f}\n'.format(np.trapz(x.psd[:fstar_idx+1]) / x.psd_power * 100.)
    else:
        xf.resample_log += ' fPSD not calculated before resampling!\n '
    xf.resample_log += '-----------------------------------------------------\n'
    if verbose:
        log.write_log(xf.resample_log)

    if plot:
        if (freq_units == 'thz') or (freq_units == 'THz'):
            axes[0].axvline(x=fstar_THz, ls='--', c='k')
            axes[1].axvline(x=fstar_THz, ls='--', c='k')
            axes[0].set_xlim([0., x.Nyquist_f_THz])
            axes[1].set_xlim([0., x.Nyquist_f_THz])
        elif (freq_units == 'red'):
            axes[0].axvline(x=0.5 / TSKIP, ls='--', c='k')
            axes[1].axvline(x=0.5 / TSKIP, ls='--', c='k')
            axes[0].set_xlim([0., 0.5 / TSKIP])
            axes[1].set_xlim([0., 0.5 / TSKIP])
        return xf, axes
    else:
        return xf
Ejemplo n.º 7
0
    def plot_periodogram(self, PSD_FILTER_W=None, freq_units='thz', freq_scale=1.0, axes=None, kappa_units=False,
                         FIGSIZE=None, **plot_kwargs):   # yapf: disable
        """
        Plot the periodogram.
          PSD_FILTER_W  = width of the filtering window
          freq_units    = 'thz'  THz
                          'red'  omega*DT/(2*pi)
          freq_scale    = rescale red frequencies by this factor (e.g. 2 --> freq = [0, 0.25])
          axes          = matplotlib.axes.Axes object (if None, create one)
          FIGSIZE       = size of the plot

        Returns a matplotlib.axes.Axes object.
        """
        # recompute PSD if needed
        if self.psd is None:
            if not self.many_currents:
                self.compute_psd()
            else:
                if self.otherMD is None:
                    raise ValueError(
                        'self.otherMD cannot be None (missing initialization?)'
                    )
                self.compute_kappa_multi(others=self.otherMD)
        if PSD_FILTER_W is None:
            if self.FILTER_WINDOW_WIDTH is None:
                self.filter_psd(0.)
        else:
            if (freq_units == 'thz') or (freq_units == 'THz'):
                self.filter_psd(freq_THz_to_red(PSD_FILTER_W, self.DT_FS))
            elif (freq_units == 'red'):
                self.filter_psd(PSD_FILTER_W)
            else:
                raise ValueError('Units not valid.')

        if kappa_units:
            # plot psd in units of kappa - the log(psd) is not converted
            psd_scale = 0.5 * self.kappa_scale
        else:
            psd_scale = 1.0
        if axes is None:
            figure, axes = plt.subplots(2, sharex=True, figsize=FIGSIZE)
        plt.subplots_adjust(hspace=0.1)
        if (freq_units == 'thz') or (freq_units == 'THz'):
            axes[0].plot(self.freqs_THz, psd_scale * self.fpsd, **plot_kwargs)
            axes[1].plot(self.freqs_THz, self.flogpsd, **plot_kwargs)
            axes[0].set_xlim([0., self.Nyquist_f_THz])
            axes[1].set_xlim([0., self.Nyquist_f_THz])
        elif (freq_units == 'red'):
            axes[0].plot(self.freqs / freq_scale, psd_scale * self.fpsd,
                         **plot_kwargs)
            axes[1].plot(self.freqs / freq_scale, self.flogpsd, **plot_kwargs)
            axes[0].set_xlim([0., 0.5 / freq_scale])
            axes[1].set_xlim([0., 0.5 / freq_scale])
        else:
            raise ValueError('Units not valid.')
        axes[0].xaxis.set_ticks_position('top')
        if kappa_units:
            axes[0].set_ylabel(r'PSD [W/mK]')
        else:
            axes[0].set_ylabel(r'PSD')
        axes[0].grid()
        axes[1].xaxis.set_ticks_position('bottom')
        axes[1].set_xlabel(r'$f$ [THz]')
        axes[1].set_ylabel(r'log(PSD)')
        axes[1].grid()
        return axes
Ejemplo n.º 8
0
def fstar_analysis(x,
                   TSKIP_LIST,
                   aic_type='aic',
                   Kmin_corrfactor=1.0,
                   plot=True,
                   axes=None,
                   FIGSIZE=None,
                   **plot_kwargs):
    """
   Simulate the resampling of x.
     TSKIP        = sampling time [steps]
     fstar_THz    = target cutoff frequency [THz]
     FILTER_W     = pre-sampling filter window width [steps]
     plot         = plot the PSD (True/False)
     PSD_FILTER_W = PSD filtering window width [chosen frequency units]
     freq_units   = 'thz'  THz
                    'red'  omega*DT/(2*pi)
     FIGSIZE      = plot figure size
   """
    if not isinstance(x, HeatCurrent):
        raise ValueError('x must be a HeatCurrent object.')

    xf = []
    for TSKIP in TSKIP_LIST:
        print 'TSKIP =  {:d}'.format(TSKIP)
        xff = resample_current(x, TSKIP, plot=False)
        xff.cepstral_analysis(aic_type, Kmin_corrfactor)
        xf.append(xff)
    FSTAR_THZ_LIST = [xff.Nyquist_f_THz for xff in xf]

    if plot:
        if axes is None:
            figure, ax = plt.subplots(2, sharex=True, figsize=FIGSIZE)
        else:
            ax = axes
        ax[0].errorbar(FSTAR_THZ_LIST, [xff.kappa_Kmin for xff in xf],
                       yerr=[xff.kappa_Kmin_std for xff in xf],
                       **plot_kwargs)
        ax[1].errorbar(FSTAR_THZ_LIST, [xff.dct.logtau_Kmin for xff in xf],
                       yerr=[xff.dct.logtau_std_Kmin for xff in xf],
                       **plot_kwargs)
        #ax[0].plot(x.freqs_THz, x.fpsd,    **plot_kwargs)
        #ax[1].plot(x.freqs_THz, x.flogpsd, **plot_kwargs)
        ax[0].xaxis.set_ticks_position('top')
        ax[0].set_ylabel(r'PSD')
        ax[0].grid()
        ax[1].xaxis.set_ticks_position('bottom')
        ax[1].set_xlabel(r'$f$ [THz]')
        ax[1].set_ylabel(r'log(PSD)')
        ax[1].grid()

        if axes is None:
            ax2 = [ax[0].twinx(), ax[1].twinx()]
            color = next(ax[0]._get_lines.prop_cycler)['color']
            color = next(ax[1]._get_lines.prop_cycler)['color']
            x.plot_periodogram(axes=ax2, c=color)
            ax[0].set_ylabel(r'$\kappa$ [W/(m*K)]')
            ax[1].set_ylabel(r'$\kappa$ [W/(m*K)]')
            return xf, ax, figure
        else:
            return xf, ax
    else:
        return xf
Ejemplo n.º 9
0
def resample_current(x,
                     TSKIP=None,
                     fstar_THz=None,
                     FILTER_W=None,
                     plot=True,
                     PSD_FILTER_W=None,
                     freq_units='thz',
                     FIGSIZE=None):
    """
   Simulate the resampling of x.
     TSKIP        = sampling time [steps]
     fstar_THz    = target cutoff frequency [THz]
     FILTER_W     = pre-sampling filter window width [steps]
     plot         = plot the PSD (True/False)
     PSD_FILTER_W = PSD filtering window width [chosen frequency units]
     freq_units   = 'thz'  THz
                    'red'  omega*DT/(2*pi)
     FIGSIZE      = plot figure size
   """
    if not isinstance(x, HeatCurrent):
        raise ValueError('x must be a HeatCurrent object.')
    if (TSKIP is not None) and (fstar_THz is not None):
        raise ValueError('Please specify either TSKIP or fstar_THz.')
    if TSKIP is None:
        if fstar_THz is None:
            raise ValueError('Please specify either TSKIP or fstar_THz.')
        else:
            TSKIP = int(round(x.Nyquist_f_THz / fstar_THz))
    if plot:
        figure, axes = plt.subplots(2, sharex=True, figsize=FIGSIZE)
        axes = x.plot_periodogram(PSD_FILTER_W, freq_units, 1.0, axes=axes)
    fstar_THz = x.Nyquist_f_THz / TSKIP
    fstar_idx = np.argmin(x.freqs_THz < fstar_THz)

    # filter and sample
    if FILTER_W is None:
        FILTER_W = TSKIP
    trajf = md.tools.filter_and_sample(x.traj, FILTER_W, TSKIP, 'rectangular')
    if not x.multicomponent:
        xf = HeatCurrent(trajf, x.units, x.DT_FS * TSKIP, x.TEMPERATURE,
                         x.VOLUME, x.FILTER_WINDOW_WIDTH * TSKIP)
    else:
        if x.otherMD is None:
            raise ValueError(
                'x.otherMD cannot be none (wrong/missing initialization?)')
        # filter_and_sample also other trajectories
        yf = []
        yf.append(trajf)
        for y in x.otherMD:
            tmp = md.tools.filter_and_sample(y.traj, FILTER_W, TSKIP,
                                             'rectangular')
            yf.append(tmp)
        xf = HeatCurrent(yf, x.units, x.DT_FS * TSKIP, x.TEMPERATURE, x.VOLUME,
                         x.FILTER_WINDOW_WIDTH * TSKIP)
    if plot:
        if (freq_units == 'thz') or (freq_units == 'THz'):
            xf.plot_periodogram(x.FILTER_WINDOW_WIDTH * 1000. / x.DT_FS,
                                'thz',
                                TSKIP,
                                axes=axes)
        elif (freq_units == 'red'):
            print PSD_FILTER_W
            print x.FILTER_WINDOW_WIDTH
            xf.plot_periodogram(x.FILTER_WINDOW_WIDTH * TSKIP,
                                'red',
                                TSKIP,
                                axes=axes)

    xf.resample_log = '-----------------------------------------------------\n' +\
                      '  RESAMPLE TIME SERIES\n' +\
                      '-----------------------------------------------------\n' +\
                      ' Original Nyquist freq  f_Ny =  {:12.5f} THz\n'.format(x.Nyquist_f_THz) +\
                      ' Resampling freq          f* =  {:12.5f} THz\n'.format(fstar_THz) +\
                      ' Sampling time         TSKIP =  {:12d} steps\n'.format(TSKIP) +\
                      '                             =  {:12.3f} fs\n'.format(TSKIP * x.DT_FS) +\
                      ' Original  n. of frequencies =  {:12d}\n'.format(x.Nfreqs) +\
                      ' Resampled n. of frequencies =  {:12d}\n'.format(xf.Nfreqs) +\
                      ' PSD      @cutoff  (pre-filter) = {:12.5f}\n'.format(x.fpsd[fstar_idx]) +\
                      '                  (post-filter) = {:12.5f}\n'.format(xf.fpsd[-1]) +\
                      ' log(PSD) @cutoff  (pre-filter) = {:12.5f}\n'.format(x.flogpsd[fstar_idx]) +\
                      '                  (post-filter) = {:12.5f}\n'.format(xf.flogpsd[-1]) +\
                      ' min(PSD)          (pre-filter) = {:12.5f}\n'.format(x.psd_min) +\
                      ' min(PSD)         (post-filter) = {:12.5f}\n'.format(xf.psd_min) +\
                      ' % of original PSD Power f<f* (pre-filter)  = {:5f}\n'.format(np.trapz(x.psd[:fstar_idx+1]) / x.psd_power * 100.) +\
                      '-----------------------------------------------------\n'
    print xf.resample_log

    if plot:
        if (freq_units == 'thz') or (freq_units == 'THz'):
            axes[0].axvline(x=fstar_THz, ls='--', c='k')
            axes[1].axvline(x=fstar_THz, ls='--', c='k')
            axes[0].set_xlim([0., x.Nyquist_f_THz])
            axes[1].set_xlim([0., x.Nyquist_f_THz])
        elif (freq_units == 'red'):
            axes[0].axvline(x=0.5 / TSKIP, ls='--', c='k')
            axes[1].axvline(x=0.5 / TSKIP, ls='--', c='k')
            axes[0].set_xlim([0., 0.5 / TSKIP])
            axes[1].set_xlim([0., 0.5 / TSKIP])
        return xf, axes
    else:
        return xf