def test_array_transff_freqslowness(self): coords = np.array( [[10.0, 60.0, 0.0], [200.0, 50.0, 0.0], [-120.0, 170.0, 0.0], [-100.0, -150.0, 0.0], [30.0, -220.0, 0.0]] ) coords /= 1000.0 coordsll = np.zeros(coords.shape) for i in np.arange(len(coords)): coordsll[i, 0], coordsll[i, 1] = utlLonLat(0.0, 0.0, coords[i, 0], coords[i, 1]) slim = 40.0 fmin = 1.0 fmax = 10.0 fstep = 1.0 sstep = slim / 2.0 transff = array_transff_freqslowness(coords, slim, sstep, fmin, fmax, fstep, coordsys="xy") transffll = array_transff_freqslowness(coordsll, slim, sstep, fmin, fmax, fstep, coordsys="lonlat") transffth = np.array( [ [0.41915119, 0.33333333, 0.32339525, 0.24751548, 0.67660475], [0.25248452, 0.41418215, 0.34327141, 0.65672859, 0.33333333], [0.24751548, 0.25248452, 1.00000000, 0.25248452, 0.24751548], [0.33333333, 0.65672859, 0.34327141, 0.41418215, 0.25248452], [0.67660475, 0.24751548, 0.32339525, 0.33333333, 0.41915119], ] ) np.testing.assert_array_almost_equal(transff, transffth, decimal=6) np.testing.assert_array_almost_equal(transffll, transffth, decimal=6)
def plotARF_slowaz(coords, slim, sstep, freqlow, freqhigh, fstep, coordsys='xy'): """ Add ability to plot range of frequency ranges """ transff = array_transff_freqslowness(coords, slim, sstep, freqlow, freqhigh, fstep, coordsys=coordsys) xgrid = np.arange(-slim, slim+sstep, sstep) slow = np.empty((len(xgrid), len(xgrid))) baz = slow.copy() for i in np.arange(len(xgrid)): for j in np.arange(len(xgrid)): # compute baz, slow slow_x = xgrid[i] slow_y = xgrid[j] slow[i, j] = np.sqrt(slow_x ** 2 + slow_y ** 2) if slow[i, j] < 1e-8: slow[i, j] = 1e-8 azimut = 180 * math.atan2(slow_x, slow_y) / math.pi baz[i, j] = azimut % -360 + 180 baz[baz < 0.0] += 360 # transform to radian, baz = np.radians(baz) cmap = cm.RdYlBu fig = plt.figure(figsize=(8, 8)) cax = fig.add_axes([0.85, 0.2, 0.05, 0.5]) ax = fig.add_axes([0.10, 0.1, 0.70, 0.7], polar=True) ax.pcolormesh(baz, slow, transff, vmin=0., vmax=1., cmap=cmap) ax.set_theta_direction(-1) ax.set_theta_zero_location("N") ax.set_ylim(0, slim) ax.grid() fig.suptitle('Array response function') ColorbarBase(cax, cmap=cmap, norm=Normalize(vmin=0., vmax=1.)) plt.show()
def test_array_transff_freqslowness(self): coords = np.array([[10., 60., 0.], [200., 50., 0.], [-120., 170., 0.], [-100., -150., 0.], [30., -220., 0.]]) coords /= 1000. coordsll = np.zeros(coords.shape) for i in np.arange(len(coords)): coordsll[i, 0], coordsll[i, 1] = utlLonLat(0., 0., coords[i, 0], coords[i, 1]) slim = 40. fmin = 1. fmax = 10. fstep = 1. sstep = slim / 2. transff = array_transff_freqslowness(coords, slim, sstep, fmin, fmax, fstep, coordsys='xy') transffll = array_transff_freqslowness(coordsll, slim, sstep, fmin, fmax, fstep, coordsys='lonlat') transffth = np.array( [[0.41915119, 0.33333333, 0.32339525, 0.24751548, 0.67660475], [0.25248452, 0.41418215, 0.34327141, 0.65672859, 0.33333333], [0.24751548, 0.25248452, 1.00000000, 0.25248452, 0.24751548], [0.33333333, 0.65672859, 0.34327141, 0.41418215, 0.25248452], [0.67660475, 0.24751548, 0.32339525, 0.33333333, 0.41915119]]) np.testing.assert_array_almost_equal(transff, transffth, decimal=6) np.testing.assert_array_almost_equal(transffll, transffth, decimal=6)
def arf(self, coords, fmin, flim, slim, sgrid): sstep = sgrid fstep = flim / 40 fmax = flim transff = array_transff_freqslowness(coords, slim, sstep, fmin, fmax, fstep, coordsys='lonlat') return transff
def plotARF_slowaz(coords, slim, sstep, freqlow, freqhigh, fstep, coordsys='xy'): """ Add ability to plot range of frequency ranges """ transff = array_transff_freqslowness(coords, slim, sstep, freqlow, freqhigh, fstep, coordsys=coordsys) xgrid = np.arange(-slim, slim + sstep, sstep) slow = np.empty((len(xgrid), len(xgrid))) baz = slow.copy() for i in np.arange(len(xgrid)): for j in np.arange(len(xgrid)): # compute baz, slow slow_x = xgrid[i] slow_y = xgrid[j] slow[i, j] = np.sqrt(slow_x**2 + slow_y**2) if slow[i, j] < 1e-8: slow[i, j] = 1e-8 azimut = 180 * math.atan2(slow_x, slow_y) / math.pi baz[i, j] = azimut % -360 + 180 baz[baz < 0.0] += 360 # transform to radian, baz = np.radians(baz) cmap = cm.RdYlBu fig = plt.figure(figsize=(8, 8)) cax = fig.add_axes([0.85, 0.2, 0.05, 0.5]) ax = fig.add_axes([0.10, 0.1, 0.70, 0.7], polar=True) ax.pcolormesh(baz, slow, transff, vmin=0., vmax=1., cmap=cmap) ax.set_theta_direction(-1) ax.set_theta_zero_location("N") ax.set_ylim(0, slim) ax.grid() fig.suptitle('Array response function') ColorbarBase(cax, cmap=cmap, norm=Normalize(vmin=0., vmax=1.)) plt.show()
def array_analysis_helper(stream, inventory, method, frqlow, frqhigh, filter=True, baz_plot=True, static3D=False, vel_corr=4.8, wlen=-1, slx=(-10, 10), sly=(-10, 10), sls=0.5, array_response=True): """ Array analysis wrapper routine for MESS 2014. :param stream: Waveforms for the array processing. :type stream: :class:`obspy.core.stream.Stream` :param inventory: Station metadata for waveforms :type inventory: :class:`obspy.station.inventory.Inventory` :param method: Method used for the array analysis (one of "FK": Frequnecy Wavenumber, "DLS": Delay and Sum, "PWS": Phase Weighted Stack, "SWP": Slowness Whitened Power). :type method: str :param filter: Whether to bandpass data to selected frequency range :type filter: bool :param frqlow: Low corner of frequency range for array analysis :type frqlow: float :param frqhigh: High corner of frequency range for array analysis :type frqhigh: float :param baz_plot: Whether to show backazimuth-slowness map (True) or slowness x-y map (False). :type baz_plot: str :param static3D: static correction of topography using `vel_corr` as velocity (slow!) :type static3D: bool :param vel_corr: Correction velocity for static topography correction in km/s. :type vel_corr: float :param wlen: sliding window for analysis in seconds, use -1 to use the whole trace without windowing. :type wlen: float :param slx: Min/Max slowness for analysis in x direction. :type slx: (float, float) :param sly: Min/Max slowness for analysis in y direction. :type sly: (float, float) :param sls: step width of slowness grid :type sls: float :param array_response: superimpose array reponse function in plot (slow!) :type array_response: bool """ if method not in ("FK", "DLS", "PWS", "SWP"): raise ValueError("Invalid method: ''" % method) sllx, slmx = slx slly, slmy = sly starttime = max([tr.stats.starttime for tr in stream]) endtime = min([tr.stats.endtime for tr in stream]) stream.trim(starttime, endtime) #stream.attach_response(inventory) stream.merge() for tr in stream: for station in inventory[0].stations: if tr.stats.station == station.code: tr.stats.coordinates = \ AttribDict(dict(latitude=station.latitude, longitude=station.longitude, elevation=station.elevation)) break if filter: stream.filter('bandpass', freqmin=frqlow, freqmax=frqhigh, zerophase=True) print stream spl = stream.copy() tmpdir = tempfile.mkdtemp(prefix="obspy-") filename_patterns = (os.path.join(tmpdir, 'pow_map_%03d.npy'), os.path.join(tmpdir, 'apow_map_%03d.npy')) def dump(pow_map, apow_map, i): np.save(filename_patterns[0] % i, pow_map) np.save(filename_patterns[1] % i, apow_map) try: # next step would be needed if the correction velocity needs to be # estimated # sllx /= KM_PER_DEG slmx /= KM_PER_DEG slly /= KM_PER_DEG slmy /= KM_PER_DEG sls /= KM_PER_DEG vc = vel_corr if method == 'FK': kwargs = dict( #slowness grid: X min, X max, Y min, Y max, Slow Step sll_x=sllx, slm_x=slmx, sll_y=slly, slm_y=slmy, sl_s=sls, # sliding window properties win_len=wlen, win_frac=0.8, # frequency properties frqlow=frqlow, frqhigh=frqhigh, prewhiten=0, # restrict output store=dump, semb_thres=-1e9, vel_thres=-1e9, verbose=False, timestamp='julsec', stime=starttime, etime=endtime, method=0, correct_3dplane=False, vel_cor=vc, static_3D=static3D) # here we do the array processing start = UTCDateTime() out = AA.array_processing(stream, **kwargs) print "Total time in routine: %f\n" % (UTCDateTime() - start) # make output human readable, adjust backazimuth to values # between 0 and 360 t, rel_power, abs_power, baz, slow = out.T else: kwargs = dict( # slowness grid: X min, X max, Y min, Y max, Slow Step sll_x=sllx, slm_x=slmx, sll_y=slly, slm_y=slmy, sl_s=sls, # sliding window properties # frequency properties frqlow=frqlow, frqhigh=frqhigh, # restrict output store=dump, win_len=wlen, win_frac=0.5, nthroot=4, method=method, verbose=False, timestamp='julsec', stime=starttime, etime=endtime, vel_cor=vc, static_3D=False) # here we do the array processing start = UTCDateTime() out = AA.beamforming(stream, **kwargs) print "Total time in routine: %f\n" % (UTCDateTime() - start) # make output human readable, adjust backazimuth to values # between 0 and 360 trace = [] t, rel_power, baz, slow_x, slow_y, slow = out.T # calculating array response if array_response: stepsfreq = (frqhigh - frqlow) / 10. tf_slx = sllx tf_smx = slmx tf_sly = slly tf_smy = slmy transff = AA.array_transff_freqslowness( stream, (tf_slx, tf_smx, tf_sly, tf_smy), sls, frqlow, frqhigh, stepsfreq, coordsys='lonlat', correct_3dplane=False, static_3D=False, vel_cor=vc) # now let's do the plotting cmap = cm.rainbow # # we will plot everything in s/deg slow *= KM_PER_DEG sllx *= KM_PER_DEG slmx *= KM_PER_DEG slly *= KM_PER_DEG slmy *= KM_PER_DEG sls *= KM_PER_DEG numslice = len(t) powmap = [] slx = np.arange(sllx-sls, slmx, sls) sly = np.arange(slly-sls, slmy, sls) if baz_plot: maxslowg = np.sqrt(slmx*slmx + slmy*slmy) bzs = np.arctan2(sls, np.sqrt(slmx*slmx + slmy*slmy))*180/np.pi xi = np.arange(0., maxslowg, sls) yi = np.arange(-180., 180., bzs) grid_x, grid_y = np.meshgrid(xi, yi) # reading in the rel-power maps for i in xrange(numslice): powmap.append(np.load(filename_patterns[0] % i)) if method != 'FK': trace.append(np.load(filename_patterns[1] % i)) npts = stream[0].stats.npts df = stream[0].stats.sampling_rate T = np.arange(0, npts / df, 1 / df) # if we choose windowlen > 0. we now move through our slices for i in xrange(numslice): slow_x = np.sin((baz[i]+180.)*np.pi/180.)*slow[i] slow_y = np.cos((baz[i]+180.)*np.pi/180.)*slow[i] st = UTCDateTime(t[i]) - starttime if wlen <= 0: en = endtime else: en = st + wlen print UTCDateTime(t[i]) # add polar and colorbar axes fig = plt.figure(figsize=(12, 12)) ax1 = fig.add_axes([0.1, 0.87, 0.7, 0.10]) # here we plot the first trace on top of the slowness map # and indicate the possibiton of the lsiding window as green box if method == 'FK': ax1.plot(T, spl[0].data, 'k') if wlen > 0.: try: ax1.axvspan(st, en, facecolor='g', alpha=0.3) except IndexError: pass else: T = np.arange(0, len(trace[i])/df, 1 / df) ax1.plot(T, trace[i], 'k') ax1.yaxis.set_major_locator(MaxNLocator(3)) ax = fig.add_axes([0.10, 0.1, 0.70, 0.7]) # if we have chosen the baz_plot option a re-griding # of the sx,sy slowness map is needed if baz_plot: slowgrid = [] transgrid = [] pow = np.asarray(powmap[i]) for ix, sx in enumerate(slx): for iy, sy in enumerate(sly): bbaz = np.arctan2(sx, sy)*180/np.pi+180. if bbaz > 180.: bbaz = -180. + (bbaz-180.) slowgrid.append((np.sqrt(sx*sx+sy*sy), bbaz, pow[ix, iy])) if array_response: tslow = (np.sqrt((sx+slow_x) * (sx+slow_x)+(sy+slow_y) * (sy+slow_y))) tbaz = (np.arctan2(sx+slow_x, sy+slow_y) * 180 / np.pi + 180.) if tbaz > 180.: tbaz = -180. + (tbaz-180.) transgrid.append((tslow, tbaz, transff[ix, iy])) slowgrid = np.asarray(slowgrid) sl = slowgrid[:, 0] bz = slowgrid[:, 1] slowg = slowgrid[:, 2] grid = spi.griddata((sl, bz), slowg, (grid_x, grid_y), method='nearest') ax.pcolormesh(xi, yi, grid, cmap=cmap) if array_response: level = np.arange(0.1, 0.5, 0.1) transgrid = np.asarray(transgrid) tsl = transgrid[:, 0] tbz = transgrid[:, 1] transg = transgrid[:, 2] trans = spi.griddata((tsl, tbz), transg, (grid_x, grid_y), method='nearest') ax.contour(xi, yi, trans, level, colors='k', linewidth=0.2) ax.set_xlabel('slowness [s/deg]') ax.set_ylabel('backazimuth [deg]') ax.set_xlim(xi[0], xi[-1]) ax.set_ylim(yi[0], yi[-1]) else: ax.set_xlabel('slowness [s/deg]') ax.set_ylabel('slowness [s/deg]') slow_x = np.cos((baz[i]+180.)*np.pi/180.)*slow[i] slow_y = np.sin((baz[i]+180.)*np.pi/180.)*slow[i] ax.pcolormesh(slx, sly, powmap[i].T) ax.arrow(0, 0, slow_y, slow_x, head_width=0.005, head_length=0.01, fc='k', ec='k') if array_response: tslx = np.arange(sllx+slow_x, slmx+slow_x+sls, sls) tsly = np.arange(slly+slow_y, slmy+slow_y+sls, sls) try: ax.contour(tsly, tslx, transff.T, 5, colors='k', linewidth=0.5) except: pass ax.set_ylim(slx[0], slx[-1]) ax.set_xlim(sly[0], sly[-1]) new_time = t[i] result = "BAZ: %.2f, Slow: %.2f s/deg, Time %s" % ( baz[i], slow[i], UTCDateTime(new_time)) ax.set_title(result) plt.show() finally: shutil.rmtree(tmpdir)
def array_transfer_helper(stream, inventory, sx=(-10, 10), sy=(-10, 10), sls=0.5, freqmin=0.1, freqmax=4.0, numfreqs=10, coordsys='lonlat', correct3dplane=False, static3D=False, velcor=4.8): """ Array Response wrapper routine for MESS 2014. :param stream: Waveforms for the array processing. :type stream: :class:`obspy.core.stream.Stream` :param inventory: Station metadata for waveforms :type inventory: :class:`obspy.station.inventory.Inventory` :param slx: Min/Max slowness for analysis in x direction. :type slx: (float, float) :param sly: Min/Max slowness for analysis in y direction. :type sly: (float, float) :param sls: step width of slowness grid :type sls: float :param frqmin: Low corner of frequency range for array analysis :type frqmin: float :param frqmax: High corner of frequency range for array analysis :type frqmax: float :param numfreqs: number of frequency values used for computing array transfer function :type numfreqs: int :param coordsys: defined coordingate system of stations (lonlat or km) :type coordsys: string :param correct_3dplane: correct for an inclined surface (not used) :type correct_3dplane: bool :param static_3D: correct topography :type static_3D: bool :param velcor: velocity used for static_3D correction :type velcor: float """ for tr in stream: for station in inventory[0].stations: if tr.stats.station == station.code: tr.stats.coordinates = \ AttribDict(dict(latitude=station.latitude, longitude=station.longitude, elevation=station.elevation)) break sllx, slmx = sx slly, slmy = sx sllx /= KM_PER_DEG slmx /= KM_PER_DEG slly /= KM_PER_DEG slmy /= KM_PER_DEG sls = sls/KM_PER_DEG stepsfreq = (freqmax - freqmin) / float(numfreqs) transff = AA.array_transff_freqslowness( stream, (sllx, slmx, slly, slmy), sls, freqmin, freqmax, stepsfreq, coordsys=coordsys, correct_3dplane=False, static_3D=static3D, vel_cor=velcor) sllx *= KM_PER_DEG slmx *= KM_PER_DEG slly *= KM_PER_DEG slmy *= KM_PER_DEG sls *= KM_PER_DEG slx = np.arange(sllx, slmx+sls, sls) sly = np.arange(slly, slmy+sls, sls) fig = plt.figure(figsize=(12, 12)) ax = fig.add_axes([0.1, 0.1, 0.8, 0.8]) #ax.pcolormesh(slx, sly, transff.T) ax.contour(sly, slx, transff.T, 10) ax.set_xlabel('slowness [s/deg]') ax.set_ylabel('slowness [s/deg]') ax.set_ylim(slx[0], slx[-1]) ax.set_xlim(sly[0], sly[-1]) plt.show()