def plotfft(signal, fmax=None, *args, **kwargs): """ Plot spectrogram """ if not isSignal(signal): warn("Method valid only at signal-level", FdpWarning) return sigfft = fft(signal, *args, **kwargs) fig = plt.figure() ax = fig.add_subplot(1, 1, 1) pcm = ax.pcolormesh(sigfft.time, sigfft.freq, sigfft.logpsd.transpose(), cmap=plt.cm.YlGnBu) pcm.set_clim([sigfft.logpsd.max() - 100, sigfft.logpsd.max() - 20]) cb = plt.colorbar(pcm, ax=ax) cb.set_label(r'$10\,\log_{10}(|FFT|^2)$ $(V^2/Hz)$') ax.set_xlabel('Time (s)') ax.set_ylabel('Frequency (kHz)') tmin = kwargs.get('tmin', 0) tmax = kwargs.get('tmax', 2) ax.set_xlim([tmin, tmax]) if fmax: if sigfft.iscomplexsignal: ax.set_ylim([-fmax, fmax]) else: ax.set_ylim([0, fmax]) ax.set_title('{} | {} | {}'.format(sigfft.shot, sigfft.parentname.upper(), sigfft.signalname.upper())) return sigfft
def powerspectrum(signal, fmax=None, *args, **kwargs): """ Calcualte bin-averaged power spectrum """ msg = "powerspectrum() will be depricated. Use Fft.binavg_psd and \ Fft.binavg_logpsd instead." warn(msg, FdpWarning) if not isSignal(signal): warn("Method valid only at signal-level", FdpWarning) return if 'tmin' not in kwargs: kwargs['tmin'] = 0.25 if 'tmax' not in kwargs: kwargs['tmax'] = 0.26 if not fmax: fmax = 250 sigfft = fft(signal, *args, **kwargs) psd = np.square(np.absolute(sigfft.fft)) # bin-averaged PSD, in dB sigfft.bapsd = 10*np.log10(np.mean(psd, axis=0)) fig = plt.figure() ax = fig.add_subplot(1, 1, 1) ax.plot(sigfft.freq, sigfft.bapsd) ax.set_ylabel(r'$10\,\log_{10}(|FFT|^2)$ $(V^2/Hz)$') ax.set_xlim([0, fmax]) ax.set_xlabel('Frequency (kHz)') ax.set_title('{} | {} | {} | {}-{} s'.format( sigfft.shot, sigfft.parentname.upper(), sigfft.signalname.upper(), kwargs['tmin'], kwargs['tmax'])) return sigfft
def plotfft(signal, fmax=None, *args, **kwargs): """ Plot spectrogram """ if not isSignal(signal): warn("Method valid only at signal-level", FdpWarning) return sigfft = fft(signal, *args, **kwargs) fig = plt.figure() ax = fig.add_subplot(1, 1, 1) pcm = ax.pcolormesh(sigfft.time, sigfft.freq, sigfft.logpsd.transpose(), cmap=plt.cm.YlGnBu) pcm.set_clim([sigfft.logpsd.max()-100, sigfft.logpsd.max()-20]) cb = plt.colorbar(pcm, ax=ax) cb.set_label(r'$10\,\log_{10}(|FFT|^2)$ $(V^2/Hz)$') ax.set_xlabel('Time (s)') ax.set_ylabel('Frequency (kHz)') if fmax: ax.set_ylim([0, fmax]) ax.set_title('{} | {} | {}'.format( sigfft.shot, sigfft.parentname.upper(), sigfft.signalname.upper())) return sigfft
def fft(obj, *args, **kwargs): """ Calculate FFT(s) for signal or container. Return Fft instance from classes/fft.py """ # default to offsetminimum=True for BES ffts offsetminimum = kwargs.pop('offsetminimum', True) normalizetodc = kwargs.pop('normalizetodc', True) if isSignal(obj): return Fft(obj, offsetminimum=offsetminimum, normalizetodc=normalizetodc, *args, **kwargs) elif isContainer(obj): signalnames = UT.get_signals_in_container(obj) ffts = [] for sname in signalnames: signal = getattr(obj, sname) ffts.append( Fft(signal, offsetminimum=offsetminimum, normalizetodc=normalizetodc, *args, **kwargs)) return ffts
def powerspectrum(signal, fmax=None, *args, **kwargs): """ Calcualte bin-averaged power spectrum """ msg = "powerspectrum() will be depricated. Use Fft.binavg_psd and \ Fft.binavg_logpsd instead." warn(msg, FdpWarning) if not isSignal(signal): warn("Method valid only at signal-level", FdpWarning) return if 'tmin' not in kwargs: kwargs['tmin'] = 0.25 if 'tmax' not in kwargs: kwargs['tmax'] = 0.26 if not fmax: fmax = 250 sigfft = fft(signal, *args, **kwargs) psd = np.square(np.absolute(sigfft.fft)) # bin-averaged PSD, in dB sigfft.bapsd = 10 * np.log10(np.mean(psd, axis=0)) fig = plt.figure() ax = fig.add_subplot(1, 1, 1) ax.plot(sigfft.freq, sigfft.bapsd) ax.set_ylabel(r'$10\,\log_{10}(|FFT|^2)$ $(V^2/Hz)$') ax.set_xlim([0, fmax]) ax.set_xlabel('Frequency (kHz)') ax.set_title('{} | {} | {} | {}-{} s'.format(sigfft.shot, sigfft.parentname.upper(), sigfft.signalname.upper(), kwargs['tmin'], kwargs['tmax'])) return sigfft
def listSignals(obj): attrnames = dir(obj) signals = [] for attrname in attrnames: attr = getattr(obj, attrname) if isSignal(attr): signals.append(attrname) return signals
def listAttributes(obj): attrnames = dir(obj) attributes = [] for attrname in attrnames: attr = getattr(obj, attrname) if not isContainer(attr) and \ not isSignal(attr) and \ not hasattr(attr, '__func__'): attributes.append(attrname) return attributes
def get_signals_in_container(container): """Return list of attribute names corresponding to valid signals""" if not isContainer(container): raise FdpError("Expecting a container object") attrnames = dir(container) valid_signals = [] for attrname in attrnames: attr = getattr(container, attrname) if isSignal(attr): try: attr[:] valid_signals.append(attr) except: print('{} is empty, ignoring'.format(attrname)) return valid_signals
def fft(obj, *args, **kwargs): """ Calculate FFT(s) for signal or container. Return Fft instance from classes/fft.py """ if isSignal(obj): return Fft(obj, *args, **kwargs) elif isContainer(obj): signalnames = UT.get_signals_in_container(obj) ffts = [] for sname in signalnames: signal = getattr(obj, sname) ffts.append(Fft(signal, *args, **kwargs)) return ffts
def testSignalAxes(self, container=None): """ Recursively parse tree Assert all signals contain 'axes' attribute Assert all signals contain 'time' attribute Assert all 'axes' elements are axis objects Assert all axis attributes are in 'axes' """ if not container: container = self.shot if not isinstance(container, fdp.classes.shot.Shot): if isinstance(container._parent, fdp.classes.shot.Shot): print('Parsing {}'.format(container._name)) else: print('Parsing {}.{}'.format(container._parent._name, container._name)) for attrname in dir(container): attr = getattr(container, attrname) if isContainer(attr): self.testSignalAxes(attr) elif isSignal(attr): self.assertTrue( hasattr(attr, 'axes'), "Signal {} does not have 'axes' attr".format(attr._name)) self.assertTrue( hasattr(attr, 'time'), "Signal {} does not have 'time' attr".format(attr._name)) self.assertTrue( isAxis(getattr(attr, 'time')), "'time' attr is not axis object for signal {}".format( attr._name)) for axisname in attr.axes: self.assertTrue( hasattr(attr, axisname), "'axes' element {} not an attribute for signal {}". format(axisname, attr._name)) axis = getattr(attr, axisname) self.assertTrue( isAxis(axis), "'axes' element {} is not axis object for signal {}". format(axisname, attr._name)) for sigattrname in dir(attr): sigattr = getattr(attr, sigattrname) if isAxis(sigattr): self.assertIn( sigattrname, attr.axes, "{} is axis but not in 'axes' attr for signal {}". format(sigattrname, attr._name))
def testSignalAxes(self, container=None): """ Recursively parse tree Assert all signals contain 'axes' attribute Assert all signals contain 'time' attribute Assert all 'axes' elements are axis objects Assert all axis attributes are in 'axes' """ if not container: container = self.shot if not isinstance(container, fdp.classes.shot.Shot): if isinstance(container._parent, fdp.classes.shot.Shot): print('Parsing {}'.format(container._name)) else: print('Parsing {}.{}'.format(container._parent._name, container._name)) for attrname in dir(container): attr = getattr(container, attrname) if isContainer(attr): self.testSignalAxes(attr) elif isSignal(attr): self.assertTrue(hasattr(attr, 'axes'), "Signal {} does not have 'axes' attr".format(attr._name)) self.assertTrue(hasattr(attr, 'time'), "Signal {} does not have 'time' attr".format(attr._name)) self.assertTrue(isAxis(getattr(attr, 'time')), "'time' attr is not axis object for signal {}".format(attr._name)) for axisname in attr.axes: self.assertTrue(hasattr(attr, axisname), "'axes' element {} not an attribute for signal {}".format( axisname, attr._name)) axis = getattr(attr, axisname) self.assertTrue(isAxis(axis), "'axes' element {} is not axis object for signal {}".format( axisname, attr._name)) for sigattrname in dir(attr): sigattr = getattr(attr, sigattrname) if isAxis(sigattr): self.assertIn(sigattrname, attr.axes, "{} is axis but not in 'axes' attr for signal {}".format( sigattrname, attr._name))
def fft(obj, *args, **kwargs): """ Calculate FFT(s) for signal or container. Return Fft instance from classes/fft.py """ # default to offsetminimum=True for BES ffts offsetminimum = kwargs.pop('offsetminimum', True) normalizetodc = kwargs.pop('normalizetodc', True) if isSignal(obj): return Fft(obj, offsetminimum=offsetminimum, normalizetodc=normalizetodc, *args, **kwargs) elif isContainer(obj): signalnames = UT.get_signals_in_container(obj) ffts = [] for sname in signalnames: signal = getattr(obj, sname) ffts.append(Fft(signal, offsetminimum=offsetminimum, normalizetodc=normalizetodc, *args, **kwargs)) return ffts
def gui(obj): if isSignal(obj): return BaseGui(obj) if isContainer(obj): return BesGui(obj)
def info(obj, *args, **kwargs): if isSignal(obj): infoSignal(obj, *args, **kwargs) elif isContainer(obj) or isShot(obj): infoContainer(obj, *args, **kwargs) return