function getSNR re-implemented in order to allow SNR calculation for stream object with more than one trace; the resulting SNR is the maximum SNR found over all traces in the stream object

This commit is contained in:
Sebastian Wehling-Benatelli 2015-06-29 16:16:59 +02:00
parent 0fcd6fab9d
commit 9aa8a5bf13

View File

@ -301,34 +301,48 @@ def crossings_nonzero_all(data):
return ((pos[:-1] & npos[1:]) | (npos[:-1] & pos[1:])).nonzero()[0] return ((pos[:-1] & npos[1:]) | (npos[:-1] & pos[1:])).nonzero()[0]
def getSNR(X, TSNR, t1): def getSNR(st, TSNR, t0):
''' """
Function to calculate SNR of certain part of seismogram relative to returns the maximum signal to noise ratio SNR (also in dB) and the
given time (onset) out of given noise and signal windows. A safety gap corresponding noise level for a given data stream ST ,initial time T0 and
between noise and signal part can be set. Returns SNR and SNR [dB] and time window parameter tuple TSNR
noiselevel.
:param: X, time series (seismogram) :param: st, time series (seismogram)
:type: `~obspy.core.stream.Stream` :type: `~obspy.core.stream.Stream`
:param: TSNR, length of time windows [s] around t0 (onset) used to determine
:param: TSNR, length of time windows [s] around t1 (onset) used to determine SNR SNR
:type: tuple (T_noise, T_gap, T_signal) :type: tuple (T_noise, T_gap, T_signal)
:param: t0, initial time (onset) from which noise and signal windows are calculated
:param: t1, initial time (onset) from which noise and signal windows are calculated
:type: float :type: float
''' :return: SNR, SNRdB, noiselevel
assert isinstance(X, Stream), "%s is not a stream object" % str(X) ..examples:
x = X[0].data >>> from obspy.core import read
t = np.arange(0, X[0].stats.npts / X[0].stats.sampling_rate, >>> st = read()
X[0].stats.delta) >>> result = getSNR(st, (6., .3, 3.), 4.67)
>>> print result
(5.1267717641040758, 7.0984398375666435, 132.89370192191919)
>>> result = getSNR(st, (8., .2, 5.), 4.67)
>>> print result
(4.645441835797703, 6.6702702677384131, 133.03562794665109)
"""
assert isinstance(st, Stream), "%s is not a stream object" % str(st)
SNR = None
noiselevel = None
for tr in st:
x = tr.data
t = np.arange(0, tr.stats.npts / tr.stats.sampling_rate,
tr.stats.delta)
# get noise window # get noise window
inoise = getnoisewin(t, t1, TSNR[0], TSNR[1]) inoise = getnoisewin(t, t0, TSNR[0], TSNR[1])
# get signal window # get signal window
isignal = getsignalwin(t, t1, TSNR[2]) isignal = getsignalwin(t, t0, TSNR[2])
if np.size(inoise) < 1: if np.size(inoise) < 1:
print 'getSNR: Empty array inoise, check noise window!' print 'getSNR: Empty array inoise, check noise window!'
return return
@ -340,9 +354,18 @@ def getSNR(X, TSNR, t1):
x = x - np.mean(x[inoise]) x = x - np.mean(x[inoise])
# calculate ratios # calculate ratios
noiselevel = np.sqrt(np.mean(np.square(x[inoise]))) new_noiselevel = np.sqrt(np.mean(np.square(x[inoise])))
signallevel = np.sqrt(np.mean(np.square(x[isignal]))) signallevel = np.sqrt(np.mean(np.square(x[isignal])))
SNR = signallevel / noiselevel newSNR = signallevel / new_noiselevel
if not SNR or newSNR > SNR:
SNR = newSNR
noiselevel = new_noiselevel
if not SNR or not noiselevel:
raise ValueError('signal to noise ratio could not be calculated:\n'
'noiselevel: {0}\n'
'SNR: {1}'.format(noiselevel, SNR))
SNRdB = 10 * np.log10(SNR) SNRdB = 10 * np.log10(SNR)
return SNR, SNRdB, noiselevel return SNR, SNRdB, noiselevel