def coherence(datai, datas): """ Calculate time domain coherence. Coherence is 1 - sin of the angle made by two vectors: di and ds. Di is data vector, and ds is the unit vector of array stack. res(di) = di - (di . ds) ds coh(di) = 1 - res(di) / ||di|| """ return 1 - l2norm(datai - dot(datai, datas) * datas) / l2norm(datai)
def coherence(datai, datas): """ Calculate time domain coherence. Coherence is 1 - sin of the angle made by two vectors: di and ds. Di is data vector, and ds is the unit vector of array stack. res(di) = di - (di . ds) ds coh(di) = 1 - res(di) / ||di|| """ return 1 - l2norm(datai - dot(datai, datas)*datas)/l2norm(datai)
def checkCoverage(gsac, opts, textra=0.0): """ Check if each seismogram has enough samples around the time window relative to ipick. """ ipick = opts.ipick tw0, tw1 = opts.twcorr saclist = gsac.saclist nsac = len(saclist) indsel, inddel = [], [] for i in range(nsac): sacdh = saclist[i] t0 = sacdh.gethdr(ipick) b = sacdh.b e = b + (sacdh.npts - 1) * sacdh.delta if b - textra > t0 + tw0 or e + textra < t0 + tw1: inddel.append(i) print('Seismogram {0:s} does not have enough sample. Deleted.'. format(sacdh.filename)) elif l2norm(sacdh.data) == 0.0: inddel.append(i) print('Seismogram {0:s} has zero l2norm. Deleted.'.format( sacdh.filename)) else: indsel.append(i) if inddel != []: gsac.saclist = [saclist[i] for i in indsel]
def snratio(data, delta, timewindow): """ Calculate signal/noise ratio within the given time window. Time window is relative, such as [-10, 20], to the onset of the arrival. """ tw0, tw1 = timewindow nn = int(round(-tw0/delta)) yn = data[:nn] ys = data[nn:] ns = len(ys) rr = l2norm(ys)/l2norm(yn)*sqrt(nn)/sqrt(ns) if l2norm(yn) == 0: print ('snr', l2norm(yn)) ### the same as: #rr = sqrt(sum(square(ys))/sum(square(yn))*nn/ns) # shoud signal be the whole time seris? #yw = data[:] #nw = len(yw) #rw = sqrt(sum(square(yw))/sum(square(yn))*nn/nw) return rr
def snratio(data, delta, timewindow): """ Calculate signal/noise ratio within the given time window. Time window is relative, such as [-10, 20], to the onset of the arrival. """ tw0, tw1 = timewindow nn = int(round(-tw0 / delta)) yn = data[:nn] ys = data[nn:] ns = len(ys) rr = l2norm(ys) / l2norm(yn) * sqrt(nn) / sqrt(ns) if l2norm(yn) == 0: print('snr', l2norm(yn)) ### the same as: #rr = sqrt(sum(square(ys))/sum(square(yn))*nn/ns) # shoud signal be the whole time seris? #yw = data[:] #nw = len(yw) #rw = sqrt(sum(square(yw))/sum(square(yn))*nn/nw) return rr
def checkCoverage(gsac, opts, textra=0.0): """ Check if each seismogram has enough samples around the time window relative to ipick. """ ipick = opts.ipick tw0, tw1 = opts.twcorr saclist = gsac.saclist nsac = len(saclist) indsel, inddel = [], [] for i in range(nsac): sacdh = saclist[i] t0 = sacdh.gethdr(ipick) b = sacdh.b e = b + (sacdh.npts-1)*sacdh.delta if b-textra > t0+tw0 or e+textra < t0+tw1: inddel.append(i) print ('Seismogram {0:s} does not have enough sample. Deleted.'.format(sacdh.filename)) elif l2norm(sacdh.data) == 0.0: inddel.append(i) print ('Seismogram {0:s} has zero l2norm. Deleted.'.format(sacdh.filename)) else: indsel.append(i) if inddel != []: gsac.saclist = [ saclist[i] for i in indsel ]
def reConverg(stack0, stack1): """ Calcuate criterion of convergence by change of stack. stack0 and stack1 are current stack and stack from last iteration. """ return l1norm(stack0-stack1)/l2norm(stack0)/len(stack0)
def ccWeightStack(saclist, opts): """ Align seismograms by the iterative cross-correlation and stack algorithm. Parameters ---------- opts.delta : sample time interval opts.ccpara : a class instance for ICCS parameters * qqhdrs : SAC headers to save quality factors: ccc, snr, coh * maxiter : maximum number of iteration * converg : convergence critrion * cchdrs : inputand output picks of cross-correlation * twcorr : time window for cross-correlation """ ccpara = opts.ccpara delta = opts.delta maxiter = ccpara.maxiter convtype = ccpara.convtype convepsi = ccpara.convepsi taperwidth = ccpara.taperwidth tapertype = ccpara.tapertype xcorr = ccpara.xcorr shift = ccpara.shift twhdrs = ccpara.twhdrs qqhdrs = ccpara.qheaders cchdrs = ccpara.cchdrs twcorr = ccpara.twcorr hdrccc, hdrsnr, hdrcoh, = qqhdrs[:3] cchdr0, cchdr1 = cchdrs if convtype == 'coef': convergence = coConverg elif convtype == 'resi': convergence = reConverg else: print('Unknown convergence criterion: {:s}. Exit.'.format(convtype)) sys.exit() out = '\n--> Run ICCS at window [{0:5.1f}, {1:5.1f}] wrt {2:s}. Write to header: {3:s}' print(out.format(twcorr[0], twcorr[1], cchdr0, cchdr1)) print(' Convergence criterion: {:s}'.format(convtype)) if ccpara.stackwgt == 'coef': wgtcoef = True else: wgtcoef = False taperwindow = taperWindow(twcorr, taperwidth) # get initial time picks tinis = array([ sacdh.gethdr(cchdr0) for sacdh in saclist]) tfins = tinis.copy() nseis = len(saclist) ccc = zeros(nseis) snr = zeros(nseis) coh = zeros(nseis) wgts = ones(nseis) stkdata = [] for it in range(maxiter): # recut data and update array stack nstart, ntotal = windowIndex(saclist, tfins, twcorr, taperwindow) windata = windowData(saclist, nstart, ntotal, taperwidth, tapertype) sdata = normWeightStack(windata, wgts, taperwidth, tapertype) stkdata.append(sdata) if it == 0: print ('=== Iteration {0:d} : epsilon'.format(it)) else: conv = convergence(stkdata[it], stkdata[it-1]) print ('=== Iteration {0:d} : {1:8.6f}'.format(it, conv)) if conv <= convepsi: print ('Array stack converged... Done. Mean corrcoef={0:.3f}'.format(mean(ccc))) break # Find time lag at peak correlation between each trace and the array stack. # Calculate cross correlation coefficient, signal/noise ratio and temporal coherence sdatanorm = sdata/l2norm(sdata) for i in range(nseis): datai = windata[i] delay, ccmax, ccpol = corrmax(sdata, datai, delta, xcorr, shift) tfins[i] += delay sacdh = saclist[i] sacdh.sethdr(cchdr1, tfins[i]) if wgtcoef: # update weight only when stackwgt == coef wgts[i] = ccpol * ccmax ccc[i] = ccmax sacdh.sethdr(hdrccc, ccc[i]) snr[i] = snratio(datai, delta, twcorr) sacdh.sethdr(hdrsnr, snr[i]) coh[i] = coherence(datai*ccpol, sdatanorm) sacdh.sethdr(hdrcoh, coh[i]) # get maximum time window for plot (excluding taperwindow) bb, ee = [], [] for i in range(nseis): sacdh = saclist[i] b = sacdh.b - tfins[i] e = b + (sacdh.npts-1)* delta bb.append(b+delta) ee.append(e-delta) b = max(bb) e = min(ee) d = (e-b)*taperwidth/2 twplot = [b+d, e-d] # calculate final stack at twplot, save to a sacdh object: stkdh # set time picks of stkdh as mean of tinis and tfins taperwindow = taperWindow(twplot, taperwidth) nstart, ntotal = windowIndex(saclist, tfins, twplot, taperwindow) windata = windowData(saclist, nstart, ntotal, taperwidth, tapertype) sdata = normWeightStack(windata, wgts, taperwidth, tapertype) tinimean = mean(tinis) tfinmean = mean(tfins) stkdh = copy.copy(saclist[0]) stkdh.thdrs = [-12345.,] * 10 stkdh.users = [-12345.,] * 10 stkdh.kusers = ['-12345 ',] * 3 stkdh.b = twplot[0] - taperwindow*0.5 + tfinmean stkdh.npts = len(sdata) stkdh.data = sdata stkdh.sethdr(cchdr0, tinimean) stkdh.sethdr(cchdr1, tfinmean) stkdh.knetwk = 'Array ' stkdh.kstnm = 'Stack ' stkdh.netsta = 'Array.Stack' stkdh.gcarc = -1 stkdh.dist = -1 stkdh.baz = -1 stkdh.az = -1 # set time window stkdh.sethdr(twhdrs[0], twcorr[0]+tfinmean) stkdh.sethdr(twhdrs[1], twcorr[1]+tfinmean) if opts.fstack is None: stkdh.filename = ccpara.fstack else: stkdh.filename = opts.fstack for sacdh, tfin in zip(saclist, tfins): sacdh.sethdr(twhdrs[0], tfin+twcorr[0]) sacdh.sethdr(twhdrs[1], tfin+twcorr[1]) quas = array([ ccc, snr, coh ]) return stkdh, stkdata, quas
def reConverg(stack0, stack1): """ Calcuate criterion of convergence by change of stack. stack0 and stack1 are current stack and stack from last iteration. """ return l1norm(stack0 - stack1) / l2norm(stack0) / len(stack0)
def ccWeightStack(saclist, opts): """ Align seismograms by the iterative cross-correlation and stack algorithm. Parameters ---------- opts.delta : sample time interval opts.ccpara : a class instance for ICCS parameters * qqhdrs : SAC headers to save quality factors: ccc, snr, coh * maxiter : maximum number of iteration * converg : convergence critrion * cchdrs : inputand output picks of cross-correlation * twcorr : time window for cross-correlation """ ccpara = opts.ccpara delta = opts.delta maxiter = ccpara.maxiter convtype = ccpara.convtype convepsi = ccpara.convepsi taperwidth = ccpara.taperwidth tapertype = ccpara.tapertype xcorr = ccpara.xcorr shift = ccpara.shift twhdrs = ccpara.twhdrs qqhdrs = ccpara.qheaders cchdrs = ccpara.cchdrs twcorr = ccpara.twcorr hdrccc, hdrsnr, hdrcoh, = qqhdrs[:3] cchdr0, cchdr1 = cchdrs if convtype == 'coef': convergence = coConverg elif convtype == 'resi': convergence = reConverg else: print('Unknown convergence criterion: {:s}. Exit.'.format(convtype)) sys.exit() out = '\n--> Run ICCS at window [{0:5.1f}, {1:5.1f}] wrt {2:s}. Write to header: {3:s}' print(out.format(twcorr[0], twcorr[1], cchdr0, cchdr1)) print(' Convergence criterion: {:s}'.format(convtype)) if ccpara.stackwgt == 'coef': wgtcoef = True else: wgtcoef = False taperwindow = taperWindow(twcorr, taperwidth) # get initial time picks tinis = array([sacdh.gethdr(cchdr0) for sacdh in saclist]) tfins = tinis.copy() nseis = len(saclist) ccc = zeros(nseis) snr = zeros(nseis) coh = zeros(nseis) wgts = ones(nseis) stkdata = [] for it in range(maxiter): # recut data and update array stack nstart, ntotal = windowIndex(saclist, tfins, twcorr, taperwindow) windata = windowData(saclist, nstart, ntotal, taperwidth, tapertype) sdata = normWeightStack(windata, wgts, taperwidth, tapertype) stkdata.append(sdata) if it == 0: print('=== Iteration {0:d} : epsilon'.format(it)) else: conv = convergence(stkdata[it], stkdata[it - 1]) print('=== Iteration {0:d} : {1:8.6f}'.format(it, conv)) if conv <= convepsi: print('Array stack converged... Done. Mean corrcoef={0:.3f}'. format(mean(ccc))) break # Find time lag at peak correlation between each trace and the array stack. # Calculate cross correlation coefficient, signal/noise ratio and temporal coherence sdatanorm = sdata / l2norm(sdata) for i in range(nseis): datai = windata[i] delay, ccmax, ccpol = corrmax(sdata, datai, delta, xcorr, shift) tfins[i] += delay sacdh = saclist[i] sacdh.sethdr(cchdr1, tfins[i]) if wgtcoef: # update weight only when stackwgt == coef wgts[i] = ccpol * ccmax ccc[i] = ccmax sacdh.sethdr(hdrccc, ccc[i]) snr[i] = snratio(datai, delta, twcorr) sacdh.sethdr(hdrsnr, snr[i]) coh[i] = coherence(datai * ccpol, sdatanorm) sacdh.sethdr(hdrcoh, coh[i]) # get maximum time window for plot (excluding taperwindow) bb, ee = [], [] for i in range(nseis): sacdh = saclist[i] b = sacdh.b - tfins[i] e = b + (sacdh.npts - 1) * delta bb.append(b + delta) ee.append(e - delta) b = max(bb) e = min(ee) d = (e - b) * taperwidth / 2 twplot = [b + d, e - d] # calculate final stack at twplot, save to a sacdh object: stkdh # set time picks of stkdh as mean of tinis and tfins taperwindow = taperWindow(twplot, taperwidth) nstart, ntotal = windowIndex(saclist, tfins, twplot, taperwindow) windata = windowData(saclist, nstart, ntotal, taperwidth, tapertype) sdata = normWeightStack(windata, wgts, taperwidth, tapertype) tinimean = mean(tinis) tfinmean = mean(tfins) stkdh = copy.copy(saclist[0]) stkdh.thdrs = [ -12345., ] * 10 stkdh.users = [ -12345., ] * 10 stkdh.kusers = [ '-12345 ', ] * 3 stkdh.b = twplot[0] - taperwindow * 0.5 + tfinmean stkdh.npts = len(sdata) stkdh.data = sdata stkdh.sethdr(cchdr0, tinimean) stkdh.sethdr(cchdr1, tfinmean) stkdh.knetwk = 'Array ' stkdh.kstnm = 'Stack ' stkdh.netsta = 'Array.Stack' stkdh.gcarc = -1 stkdh.dist = -1 stkdh.baz = -1 stkdh.az = -1 # set time window stkdh.sethdr(twhdrs[0], twcorr[0] + tfinmean) stkdh.sethdr(twhdrs[1], twcorr[1] + tfinmean) if opts.fstack is None: stkdh.filename = ccpara.fstack else: stkdh.filename = opts.fstack for sacdh, tfin in zip(saclist, tfins): sacdh.sethdr(twhdrs[0], tfin + twcorr[0]) sacdh.sethdr(twhdrs[1], tfin + twcorr[1]) quas = array([ccc, snr, coh]) return stkdh, stkdata, quas