def mass_process(): """main processing function """ # common parameter set start = '2018-001' end = '2018-072' decimate_by = 5 for i in range(1,23): # if i in [10,11,17]: # continue station = 'RD{:0>2}'.format(i) # for channel in ['HHZ','HHN','HHE']: for channel in ['HHN','HHE']: data,response = gather_data(sta=station,cha=channel, start=start,end=end) if not data: continue ppsd = analyze_noise(data,response) # save ppsd and figure output_name = '{s}.{c}.{st}.{en}.db{d}'.format(s=station, c=channel, st=start, en=end, d=decimate_by) npz_filepath = pathnames()['ppsd'] + '{}.npz'.format(output_name) png_filepath = pathnames()['plots'] + \ 'spectral/ppsd_plots/PPSD_HOLD/{}.png'.format( output_name) ppsd.save_npz(npz_filepath)
def mesh_mapper_2d(mesh,show=True,save=False): """plot an xyz topography file as a 3d figure. lags out hard because our topography data is so large and high resolution """ filepath = pathnames()['xyz'] + meshes[mesh] data = np.genfromtxt(filepath) x = data[:,0] y = data[:,1] z = data[:,2] f = plt.scatter(x,y,c=z,cmap='inferno') plt.scatter(x=[225024.7252923958],y=[5300565.314050345],s=100,marker='o') #kaikoura plt.scatter(x=[215226.826279],y=[5298229.940908],s=100,marker='v') #NZ.KHZ plt.ticklabel_format(style='sci', axis='both', scilimits=(0,0)) plt.xlim([min(x),max(x)]) plt.ylim([min(y),max(y)]) plt.title(mesh) # cbar = plt.colorbar(format='%.0e') # cbar.ax.set_ylabel('elevation [m]', rotation=90) if save: figtitle = "mesh_{m}.png".format(m=mesh) figfolder = join(pathnames()['kupeplots'],"meshcompare",figtitle) plt.savefig(figfolder,dpi=400) if show: plt.show() return f
def collect_files(date): """grab datafile by dates """ date = UTCDateTime(date) pickle = pathnames()['data'] + "TEROR/{y}/XX/*/pickle".format(y=date.year) pickle_files = glob.glob(os.path.join(pickle,'*{}*'.format(date.julday))) npz = pathnames()['data'] + "TEROR/{y}/XX/*/npz".format(y=date.year) npz_files = glob.glob(os.path.join(npz,'*{}*'.format(date.julday))) if not pickle_files: print("No files found") return None return pickle_files, npz_files
def waveform_getter(code,mesh,bounds=None): """grab mseed data from synthetics folder, filter if necessary available inputs for mesh: ETOPO1, SRTM15P, SRTM30P """ # initialization net,sta,loc,cha = code.split('.') datapath = join(pathnames()['syns'],'2018p130600_meshTest',mesh,'') datafiles = glob.glob(join(datapath,'{n}.{s}*.mseed'.format(n=net,s=sta))) # data checkstop if not datafiles: print('No data files for {n}.{s} in mesh {m} found'.format(n=net, s=sta, m=mesh)) return None # read in datafiles st = Stream() for d in datafiles: st += read(d) # filter if necessary, convert bounds from seconds to frequency if bounds: freqmin = 1/bounds[1] freqmax = 1/bounds[0] st.filter('bandpass',freqmin=freqmin,freqmax=freqmax) return st
def mesh_mapper_3d(): """plot an xyz topography file as a 3d figure. lags out hard because our topography data is so large and high resolution """ from matplotlib import cm from matplotlib.mlab import griddata from mpl_toolkits.mplot3d import Axes3D filepath = (pathnames()['xyz'] + 'topo_SRTM30P_utm60H_ismooth0_553_622_1000m_surf.xyz') data = np.genfromtxt(filepath) x = data[:343966,0] y = data[:343966,1] z = data[:343966,2] fig = plt.figure() ax = fig.add_subplot(111, projection='3d') xi = np.linspace(min(x), max(x)) yi = np.linspace(min(y), max(y)) X, Y = np.meshgrid(xi, yi) Z = griddata(x, y, z, xi, yi) surf = ax.plot_surface(X, Y, Z, rstride=5, cstride=5, cmap=cm.jet, linewidth=1) ax.set_zlim3d(np.min(Z), np.max(Z)) fig.colorbar(surf) plt.show()
def create_composite(): """waveform comparisons of synthetics with a map showing source-receiver pair and connecting lines, potential option to plot onto real mesh (might be intensive) """ # meshlist = ["ETOPO1_496_566","SRTM30P_552_620","ETOPO1_553_622",] meshlist = ["SRTM30P_552_620","ETOPO1_553_622",] boundlist=[[3,30],[10,30]] # create station list synth_list = (pathnames()['syns'] + '2018p130600_meshTest/ETOPO1_496_566/*.mseed') stations = glob.glob(synth_list) station_list = [] for s in stations: _,S,_,_,_ = s.split('.') station_list.append(S) station_list = list(set(station_list)) station_list = ["PUZ","MWZ","NNZ","TOZ"] for sta in station_list: # try: code = "NZ.{}..HHZ".format(sta) f_es = event_station_plotter(sta,show=False,save=True) plt.close() for bounds in boundlist: f_wf,axes = waveform_plotter(code,bounds, meshlist,show=False,save=True) plt.close()
def initial_data_gather(code, event_id, bounds): """grab data """ st, inv, cat = getdata.event_stream(code=code, event_id=event_id) # bannister data st_ban = Stream() for Co in ["HHZ", "HHN", "HHE"]: ban_path = glob.glob(pathnames()['mseed'] + 'GA/{e}/*GA01.{c}*'.format(e=event_id, c=Co)) st_ban += read(ban_path[0]) origin_time = cat[0].origins[0].time st_proc = procmod.preprocess(st, inv=inv, output="DISP") for tr in st_proc: tr.data *= (10**9) # meters to micrometers st_ban_proc = procmod.preprocess(st_ban) st_alltogether = st_proc + st_ban_proc # st_alltogether.trim(origin_time,origin_time+300) procmod.trimstreams(st_alltogether) st_alltogether.filter("bandpass", freqmin=1 / bounds[1], freqmax=1 / bounds[0]) return st_alltogether
def mesh_differencer_2d(mesh1,mesh2,show=True,save=False): """difference the elevation of mesh1 and mesh2 """ # MESH 1 filepath1 = pathnames()['xyz'] + meshes[mesh1] # filepath1=('topo_SRTM30P_utm60H_ismooth0_553_622_1000m_surf.xyz') data1 = np.genfromtxt(filepath1) x1 = data1[:,0] y1 = data1[:,1] z1 = data1[:,2] # MESH 2 filepath2 = pathnames()['xyz'] + meshes[mesh2] # filepath2=('topo_SRTM15P_utm60H_ismooth0_553_622_1000m_surf.xyz') data2 = np.genfromtxt(filepath2) x2 = data2[:,0] y2 = data2[:,1] z2 = data2[:,2] zdiff = z1-z2 # plot it f,ax = plt.subplots() plt.scatter(x1,y1,c=zdiff,cmap='seismic') # formatting plt.ticklabel_format(style='sci', axis='both', scilimits=(0,0)) plt.xlim([min(x1),max(x1)]) plt.ylim([min(y1),max(y1)]) plt.title("Mesh difference between {m1} and {m2}".format(m1=mesh1, m2=mesh2) ) globalmax = math.ceil(max([min(zdiff),max(zdiff)])) norm = mpl.colors.Normalize(vmin=min(zdiff),vmax=max(zdiff)) cbar = plt.colorbar()#boundaries= # np.linspace(min(zdiff),max(zdiff),201)) cbar.ax.set_ylabel('elevation difference [m]', rotation=90) if show: plt.show() if save: figtitle = "meshdiff_{m1}_{m2}.png".format(m1=mesh1,m2=mesh2) figfolder = join(pathnames()['kupeplots'],"meshcompare",figtitle) plt.savefig(figfolder,dpi=400)
def event_station_plotter(station,mesh='SRTM30P', event="2018p130600",save=False,show=True): """given an event and a station, plot them on a map """ # find station coordinates nz_bb_path = pathnames()['data'] + 'STATIONXML/nz_BB_coords.npz' nz_bb = np.load(nz_bb_path) nz_bb_names = nz_bb['NAME'] bb_ind = np.where(nz_bb_names==station)[0][0] sta_lat = nz_bb['LAT'][bb_ind] sta_lon = nz_bb['LON'][bb_ind] # static event coordinates - but could get from CMTSOLUTIONS easily ev_lat = -39.9490 ev_lon = 176.2995 # convert coordinates to UTM60 sta_x,sta_y = lonlat_utm(sta_lon,sta_lat) ev_x,ev_y = lonlat_utm(ev_lon,ev_lat) # call mesh plotter and superimpose station and event f = mesh_mapper_2d(mesh,show=False,save=False) # plt.figure(f) plt.plot([sta_x,ev_x],[sta_y,ev_y],'k',zorder=4) plt.scatter(sta_x,sta_y,s=22.5,c='b',marker='v', edgecolors='k',linewidths=1,zorder=5) plt.annotate(s="NZ.{}".format(station),xy=(sta_x,sta_y),zorder=6,color='w') plt.scatter(ev_x,ev_y,s=22.5,c='r',marker='o', edgecolors='k',linewidths=1,zorder=5) plt.annotate(s='2018p130600',xy=(ev_x,ev_y),zorder=6,color='w') plt.xlabel('X (UTM-60)') plt.ylabel('Y (UTM-60)') if save: figtitle = "evsta_{s}.png".format(s=station) figfolder = join(pathnames()['kupeplots'],"meshcompare",figtitle) plt.savefig(figfolder,dpi=100) if show: plt.show() return f
def single_process(): start = '2018-028' end = '2018-057' station = 'RD01' channel = 'HHZ' decimate_by = 5 data,response = gather_data(sta=station,cha=channel,start=start,end=end) ppsd = analyze_noise(data,response,decimate_by) # save ppsd and figure output_name = '{s}.{c}.{st}.{en}.db{d}'.format(s=station, c=channel, st=start, en=end, d=decimate_by) npz_filepath = pathnames()['ppsd'] + '{}.npz'.format(output_name) png_filepath = pathnames()['plots'] + \ 'spectral/ppsd_plots/PPSD_HOLD/{}.png'.format(output_name) ppsd.plot(filename=png_filepath,cmap=pqlx,show_mean=True,show=True)
def points_over_sigma(Rm): """determine which points lie over 2sigma for minute arrays """ meanstdfilepath = pathnames()['data'] + 'TEROR/MEANSTD_night_2338.npz' meanstdfile = np.load(meanstdfilepath) mean = meanstdfile['Rm_mean'] std = meanstdfile['Rm_sigma'] two_sigma = mean + (2*std) for i,rmpoint in enumerate(Rm): if rmpoint < two_sigma: Rm[i] = np.nan return Rm
def check_save(code_set, st=None, TEORRm=None, night=False): """either check if processing has been run before, or save files to specific path. [Check] initiated by default, [save] initiated if the function is given an argument for TEORRm :type code_set: str :param code_set: instrument code, set in main :type st: obspy stream :param st: stream containing preprocessed data :type TEORRm: list of numpy arrays :param TEORRm: list of arrays containing filtered waveform data """ # set up pathing net, sta, loc, cha, d, year, jday = code_set.split('.') outpath = os.path.join(pathnames()['data'], 'TEROR', year, net, sta, '{f}') nightcheck = "" if night: nightcheck = "_night" outfile = "{n}.{s}.{l}.{y}.{j}{N}.{f}".format(n=net, s=sta, l=loc, y=year, j=jday, N=nightcheck, f='{f}') output = os.path.join(outpath, outfile) pickle_path = output.format(f='pickle') npz_path = output.format(f='npz') for pathcheck in [pickle_path, npz_path]: if not os.path.exists(os.path.dirname(pathcheck)): os.makedirs(os.path.dirname(pathcheck)) # save stream as a pickle to preserve non-mseed components # save passband arrays into npz file, dynamically sort out dict components** if st: if not os.path.exists(pickle_path): st.write(pickle_path, format="PICKLE") if TEORRm: np.savez(npz_path, **TEORRm) return True else: return False # check arrays else: if not os.path.exists(npz_path): npz_path = False if not os.path.exists(pickle_path): pickle_path = False return {"npz": npz_path, "pickle": pickle_path}
def multi_component_ppsd(comp,specific,avg='median'): """Return average arrays for each station in a given folder, choice of component, can be N/E/Z/* Choice of average available from the PPSD objects """ fidtmplt = "RD{s:0>2}.HH{c}*" if specific == "ALL": folder = 'FATHOM/*' else: folder = 'FATHOM/{}'.format(specific) folderlist = glob.glob(os.path.join(pathnames()['ppsd'],folder)) averages,stations = [],[] for F in folderlist: print(F) # check range of stations available using filenames allfiles = glob.glob(os.path.join(F,'*HH*.npz')) allfiles.sort() lowrange = int(os.path.basename(allfiles[0]).split('.')[0][2:]) highrange = int(os.path.basename(allfiles[-1]).split('.')[0][2:]) # loop by station and inner loop by components per station for i in range(lowrange,highrange+1): files = glob.glob(os.path.join(F,fidtmplt.format(s=i,c=comp))) if not files: print('no files',fidtmplt.format(s=i,c=comp)) continue inneraverages = [] for fid in files: ppsd = PPSD.load_npz(fid) if avg == 'mean': average = ppsd.get_mean() elif avg == 'mode': average = ppsd.get_mode() elif avg == 'median': average = ppsd.get_percentile(percentile=50) inneraverages.append(average[1]) outeraverage = np.mean(np.array(inneraverages),axis=0) averages.append(outeraverage) stations.append("RD{:0>2}".format(i)) periods = average[0] if specific == "ALL": stations,averages = collapse_stations(stations,averages) return stations,periods,averages
def trace_trench(m): """trace the hikurangi trench on a basemap object 'm' """ trenchcoordspath = pathnames()['data'] + \ 'DURATIONS/hikurangiTrenchCoords.npz' trenchcoords = np.load(trenchcoordspath) lats = trenchcoords['LAT'] lons = trenchcoords['LON'] x, y = m(lons, lats) # interpolate points to make a smoother curve xprime = np.flip(x, axis=0) yprime = np.flip(y, axis=0) xprimenew = np.linspace(x.min(), x.max(), 100) yprimenew = np.interp(xprimenew, xprime, yprime) m.plot(xprimenew, yprimenew, '--', linewidth=1.25, color='k', zorder=2)
def plot_streams(st, bounds, save=False, show=True): """plot 6 streams in 3 subplot figure """ c1, c2, c3 = "Z", "N", "E" f, (ax1, ax2, ax3) = plt.subplots(3, sharex=True, sharey=False, figsize=(9, 5), dpi=200) # create time axis stats = st[0].stats net, sta, loc, cha = st[0].get_id().split('.') t = np.linspace(0, stats.endtime - stats.starttime, stats.npts) # axes lists for plotting axes = [ax1, ax2, ax3] obs_list = ["HH{}".format(c1), "HH{}".format(c2), "HH{}".format(c3)] # plot for ax, obs in zip(axes, obs_list): obs_select = st.select(channel=obs)[0] A = ax.plot(t, obs_select.data, color='k', label=obs_select.get_id()) plotmod.pretty_grids(ax) # final plot ax1.set_xlim([t.min(), t.max()]) ax1.set_title("{e} {s} [{t0}-{t1}s]".format(e=stats.starttime, s=stats.station, t0=bounds[0], t1=bounds[1])) ax1.set_ylabel(c1) ax2.set_ylabel("velocity (m/s)\n{}".format(c2)) ax3.set_ylabel(c3) ax3.set_xlabel("time (sec)") if save: figtitle = "{s}_{t}.png".format(s=stats.station, t=TART) figfolder = join(pathnames()['plots'], "noncategorical", figtitle) plt.savefig(figfolder, dpi=100) if show: plt.show() return f
def waveform_plotter(code,bounds,meshlist,show=True,save=False): """call waveform_getter for the same station in each mesh and plot the waveforms superimposed to see the differences """ net,sta,loc,cha = code.split('.') colordict = {"ETOPO1_553_622":'r', "ETOPO1_496_566":'c', "SRTM30P_552_620":'g', "SRTM15P":'b' } # dynamically plot waveforms based on meshlist f,axes = setup_plot(3) for i,mesh in enumerate(meshlist): st = waveform_getter(code,mesh,bounds) if i == 0: stats = st[0].stats t = np.linspace(0,stats.endtime-stats.starttime,stats.npts) for ax,comp in zip(axes,['N','E','Z']): st_comp = st.select(component=comp) plotlabel = "{m} {n}.{s}".format(m=mesh,n=net,s=sta) ax.plot(t,st_comp[0].data,c=colordict[mesh],label=plotlabel) # post-formatting for ax,comp in zip(axes,['N','E','Z']): ax.set_ylabel('{} disp [m]'.format(comp)) ax.legend(prop={"size":10}) axes[-1].set_xlabel('Time [s]') plt.xlim([0,300]) plt.sca(axes[0]) plt.title('Mesh Waveform Comparison [{b0}-{b1}s]'.format(b0=bounds[0], b1=bounds[1])) if save: figtitle = "meshwaveforms_{n}.{s}_{b0}-{b1}.png".format(n=net,s=sta, b0=bounds[0], b1=bounds[1]) figfolder = join(pathnames()['kupeplots'],"meshcompare",figtitle) plt.savefig(figfolder,dpi=100) if show: plt.show() return f,axes
def get_ito_data(event_id, station="EBPR-1"): """Retrieve data from Ito-san internally. mseed files converted from sac files given to us through email correspondence with Ito-san :type event_id: str :param event_id: geonet quake label :type station: str :param station: station name :rtype st: obspy stream :return st: stream object containing waveform """ datapath = pathnames()["mseeds"] + 'ITO' fid = "{e}_{s}_vel.mseed".format(e=event_id, s=station) filepath = os.path.join(datapath, fid) if not os.path.exists: print("station event pair doesn't exist") sys.exit() st = read(filepath) return st
def create_lobs_nparray(): """quickly take the dataless STATIONXML for the Hobitss stations and convert into my own standard coord file """ from obspy import read_inventory names, lats, lons, depths = [], [], [], [] inv = read_inventory('plotYH_HOBITSS_stations_only.xml') for net in inv: for sta in net: names.append(sta.code) lats.append(sta.latitude) lons.append(sta.longitude) depths.append(sta.elevation * -1) dictout = {"NAME": names, "LAT": lats, "LON": lons, "DEPTH": depths} pathout = pathnames()['data'] + 'STATIONXML' fullout = os.path.join(pathout, 'EBS_LOBS_coords.npz') np.savez(fullout, **dictout)
def process_que(): event_list = glob.glob(pathnames()['mseed'] + 'GA/*') code = "NZ.KNZ.*.HH*" check_list = [] event_work = [] for event in event_list: try: event_id = os.path.basename(event) st = initial_data_gather(code, event_id, bounds) except Exception as e: print("=" * 79) traceback.print_exc() print("=" * 79) continue check = input("y or n") check_list.append(check) event_work.append(event) for i, j in zip(event_work, check_list): print(os.path.basename(i), j)
def already_processed(): """check what days have already been processed, pretty print by day number """ import glob output_path = os.path.join(pathnames()['data'], 'TEROR', '201?', '*', '*', 'pickle', '*.pickle') allfiles = glob.glob(output_path) jday_list, sta_list = np.array([]), np.array([]) for fid in allfiles: fid = os.path.basename(fid) net, sta, loc, year, jday, _ = fid.split('.') jday_list = np.append(jday_list, jday) sta_list = np.append(sta_list, sta) jday_set = sorted(set(jday_list)) for J in jday_set: indices = np.where(jday_list == J)[0] print(J, end=": ") for i in indices: print(sta_list[i], end=" ") print(' ') sys.exit()
def plot_two_streams(st, bounds, twinax=False, save=False, show=True): """plot 6 streams in 3 subplot figure """ c1, c2, c3 = "Z", "N", "E" f, (ax1, ax2, ax3) = plt.subplots(3, sharex=True, sharey=False, figsize=(9, 5), dpi=200) # create time axis stats = st[0].stats net, sta, loc, cha = st[0].get_id().split('.') t = np.linspace(0, stats.endtime - stats.starttime, stats.npts) # axes lists for plotting axes = [ax1, ax2, ax3] twin_axes = [ax1, ax2, ax3] if twinax: ax1a, ax2a, ax3a = ax1.twinx(), ax2.twinx(), ax3.twinx() twin_axes = [ax1a, ax2a, ax3a] ax2a.set_ylabel("velocity (m/s)") obs_list = ["HH{}".format(c1), "HH{}".format(c2), "HH{}".format(c3)] st_1 = st.select(station="*Z") st_2 = st.select(station="GA*") # plot for ax, tax, obs in zip(axes, twin_axes, obs_list): obs_select = st_1.select(channel=obs)[0] obs_2_select = st_2.select(channel=obs)[0] A = ax.plot(t, obs_select.data, color='k', label=obs_select.get_id()) B = tax.plot(t, obs_2_select.data, color='r', label=obs_2_select.get_id()) plotmod.pretty_grids(ax) lines = A + B labels = [l.get_label() for l in lines] ax.legend(lines, labels, prop={"size": 5}) plotmod.pretty_grids(tax) plotmod.align_yaxis(ax, 0, tax, 0) # final plot ax1.set_xlim([t.min(), t.max()]) ax1.set_title("{e} {s} [{t0}-{t1}s]".format(e=event_id, s=stats.station, t0=bounds[0], t1=bounds[1])) ax1.set_ylabel(c1) ax2.set_ylabel("displacement (m)\n{}".format(c2)) ax3.set_ylabel(c3) ax3.set_xlabel("time (sec)") if save: figtitle = "{e}_{s}.png".format(e=event_id, s=stats.station) figfolder = join(pathnames()['kupeplots'], "obsynth_plots", figtitle) plt.savefig(figfolder, dpi=200) if show: plt.show() return f
def mean_std_creator(night=False, overwrite=True): """determine mean and 1-sigma values for all TEORRm arrays, to be used for counting tremors. :type night: bool :param night: consider only nighttime files with suffix '_night' :type overwrite: bool :param overwrite: if True, create new file, if False, use file available :rtype sig_dict: dict :return sig_dict: contains mean, median and 1-sigma values for each ratio array Rs,Rm and Rh """ filepath = os.path.join(pathnames()['data'], 'TEROR', '201?', '*', '*', 'npz', '') outpath_template = os.path.join(pathnames()['data'], 'TEROR', 'MEANSTD{N}_{C}.npz') N = "_night" if not night: N = "" # use the file currently available, avoid creating new if not overwrite: if verbose: print("[mean/std overwrite turned OFF, reading in place]") outpath_inplace = glob.glob(outpath_template.format(N=N, C="*"))[0] sig_dict = np.load(outpath_inplace) return sig_dict # during normal processing, if file exists, read terorfiles = glob.glob(filepath + 'XX*{N}.npz'.format(N=N)) outpath = outpath_template.format(N=N, C=len(terorfiles)) if os.path.exists(outpath): if verbose: print("[mean/std file exists, reading...]") sig_dict = np.load(outpath) return sig_dict # if new file, calculate all averages etc. sig_dict = {} for choice in ['Rs', 'Rm', 'Rh']: means_, medians_, one_sigmas_ = [], [], [] for count, fid in enumerate(terorfiles): TEORRm = np.load(fid) ratio = TEORRm[choice] means_.append(np.mean(ratio)) medians_.append(np.median(ratio)) one_sigmas_.append(np.std(ratio)) # dictionary sig_dict["{}_mean".format(choice)] = np.mean(means_) sig_dict["{}_median".format(choice)] = np.mean(medians_) sig_dict["{}_sigma".format(choice)] = np.mean(one_sigmas_) if verbose: print("[creating mean/std file...]") np.savez(outpath, **sig_dict) # delete any previous files that are superceded by current write outpath_wild = outpath_template.format(N=N, C="*") files_to_delete = glob.glob(outpath_wild) files_to_delete.remove(outpath) if files_to_delete: for fid in files_to_delete: os.remove(fid) return sig_dict
def stacked_plot(code, x, N, E, **options): """multiple stations plotted in a stacked plot to show waveform coherence sts should be a stream of all components """ net, sta, loc, cha, d, year, jday = code.split('.') f, (ax1, ax2, ax3) = plt.subplots(3, sharex=True, sharey=False, figsize=(11.69, 8.27), dpi=75) ax3a = ax3.twinx() # create t axis to match x TEORRm_ = options['TEORRm_list'][0] x_Rm = np.linspace(x.min(), x.max(), len(TEORRm_['Rm'])) x_Rs = np.linspace(x.min(), x.max(), len(TEORRm_['Rs'])) step_up = 0 n_ano, e_ano = options['ano_list'] for N_, E_, T_, TEROR_, O_, Nano_, Eano_ in zip(N, E, options['tremor_list'], options['TEORRm_list'], options['sig_list'], n_ano, e_ano): Rm_ = TEROR_['Rm'] Rs_ = TEROR_['Rs'] N_ += step_up E_ += step_up T_ += step_up ax1.set_title('[Tremor Detection] {}\n \ North (2-8Hz Bandpass, 0-1 norm, 0.5 cutoff)'.format(jday)) ax1.plot(x, N_) ax1.plot(x, T_, 'k') ax2.set_title('East') ax2.plot(x, E_) ax2.plot(x, T_, 'k') ax3.set_title('Ratio median detection threshold and 2-sigma detection') ax3.plot(x_Rm, Rm_, '|-', markersize=1.25) # plot Rs list on twin ax3 ax3a.plot(x_Rs, Rs_, '|-', markersize=1.25) ax3.scatter(x_Rm, O_, marker='o', s=4, zorder=10) ax3.axhline(y=options['horizontal_line'], xmin=x.min(), xmax=x.max(), c='k') ax3.set_xlabel('NZ local time (hours)') for ax, ano in zip([ax1, ax2], [Nano_, Eano_]): ax.annotate(ano, xy=(x.min(), step_up), xytext=(x.min(), step_up), fontsize=6) step_up += 0.25 # ax3.legend(prop={"size":7.5}) for ax in [ax1, ax2, ax3, ax3a]: pretty_grids(ax) # ax.set_xlim([18,30]) if night else ax.set_xlim([x.min(),x.max()]) ax.set_xlim([x.min(), x.max()]) plt.tight_layout() if options['save']: fig_path = pathnames()['plots'] + 'tremor/' fig_name = code_set.format(c='?') + '.png' fig_out = os.path.join(fig_path, fig_name) plt.savefig(fig_out, dpi=200) if options['show']: plt.show() plt.close()
def loop_waveform_plotter(event_id, corners, choice='GN', show=True, save=False, savez=True): """run script to call waveform process/plotter and save all duration values into an npz file which will be called by the plotter """ filedict = { "GN": "NZ_BB_coords.npz", "ITO": "ITO_OBP_coords.npz", "YH": "LOBS_coords.npz" } stationfile = filedict[choice] # collect station information npzfolder = pathnames()['data'] + 'STATIONXML' sta = np.load(os.path.join(npzfolder, stationfile)) names, lats, lons = sta['NAME'], sta['LAT'], sta['LON'] # numpy array for saving duration information pathout = pathnames()['data'] + 'DURATIONS' stationfile = '{e}_{b0}_{b1}_durations.npz'.format(e=event_id, b0=bounds[0], b1=bounds[1]) allout = os.path.join(pathout, stationfile) # geonet data starts off the numpy list if choice == "GN": durations = [] for i, sta in enumerate(names): if sta != 'MWZ': continue try: if true_if_outside_bounds(lats[i], lons[i], corners): durations.append(np.nan) print(sta, 'outside bounds') continue code = 'NZ.{}.*.HH?'.format(sta) duration = process_and_plot_waveforms(event_id, code, choice=choice, show=show, save=save) if not duration: continue durations.append(duration) except Exception as e: print('\t{} {}'.format(sta, e)) durations.append(np.nan) plt.close() continue dictout = { "NAME": names, "DURATION": durations, "LAT": lats, "LON": lons } # ITO and LOBS data will append to the numpy list else: # import numpy array to be appended to sta = np.load(allout) nameO, latO, lonO, durO = sta['NAME'], sta['LAT'], sta['LON'], sta[ 'DURATION'] # only certain event station pairs exist for ITO data if choice == "ITO": mseedpath = pathnames()['mseeds'] + 'ITO/{}*'.format(event_id) eventfiles = glob.glob(mseedpath) names = [] for fid in eventfiles: names.append(fid.split('_')[1]) # for ITO and LOBS data,. the process is the same from here except names newnames, newlats, newlons, newdurs = [], [], [], [] for i, sta in enumerate(names): try: if true_if_outside_bounds(lats[i], lons[i], corners): print('\t {} is outside bounds'.format(sta)) continue ind = np.where(np.array(names) == sta)[0][0] if choice == "YH": if 'EBS' in sta: continue code = "YH.{}.*.?H?".format(sta) else: code = sta duration = process_and_plot_waveforms(event_id, code, choice=choice, show=show, save=save) if not duration: continue newdurs.append(duration) newnames.append(names[ind]) newlats.append(lats[ind]) newlons.append(lons[ind]) except Exception as e: print('\t' + sta) newdurs.append(np.nan) plt.close() continue # output arrays are cats of old and new nameO = np.concatenate((nameO, np.array(newnames))) latO = np.concatenate((latO, np.array(newlats))) lonO = np.concatenate((lonO, np.array(newlons))) durO = np.concatenate((durO, np.array(newdurs))) dictout = {"NAME": nameO, "DURATION": durO, "LAT": latO, "LON": lonO} if savez: np.savez(allout, **dictout)
def process_and_plot_waveforms(event_id, code, threshold_choice=0.2, choice="GN", show=False, save=False): """create first section of composite, two waveforms showing vertical and groundmotion with proper formatting etc. :type choice: str :param choice: which stations to process, available GEONET ["GN"], HOBITSS ["YH"] and ITO-SANS data ["ITO"] :rtype duration: float :return duration: value of duration in seconds, for use in plotting """ # setup the plot early to add things during processing f, ax1, ax2 = setup_plot() # PROCESS by network if choice == "GN": st_raw, inv, event = get_geonet_data(event_id, code) st = preprocess(st_raw, inv, event) code = code.split('.')[1] elif choice == "ITO": st_raw = get_ito_data(event_id, code) for tr in st_raw: tr.stats.starttime -= (17 * 60 + 56.346) _, _, event = get_geonet_data(event_id, 'NZ.PUZ.*.HH?') st = preprocess(st_raw, event=event) st.resample(20) for ax in [ax1, ax2]: ax.set_ylabel('velocity ($\mu$m/s)') elif choice == "YH": st_raw, inv = get_lobs_data(event_id, code) _, _, event = get_geonet_data(event_id, 'NZ.PUZ.*.HH?') st = preprocess(st_raw, inv, event) code = code.split('.')[1] vertical,groundmotion,whereover,groundmotion_over,threshold = \ amplitude_threshold(st,threshold_choice) # calculate duration from counted samples stats = st[0].stats duration = len(whereover[0]) / stats.sampling_rate if (show == False) and (save == False): plt.close() return duration # PLOT WAVEFORMS t = np.linspace(0, stats.endtime - stats.starttime, stats.npts) ax1.plot(t, vertical, 'k') ax2.plot(t, groundmotion, 'k', zorder=3) ax2.plot(t, groundmotion_over, 'r', zorder=4, label='Duration = {}s'.format(int(duration))) ax2.axhline(xmin=t[0], xmax=t[-1], y=threshold, zorder=2, color='gray', linestyle='-.', linewidth=1.5, label='20% peak amplitude') # formatting ax1.set_title(code + ' [{b0}-{b1}s]'.format(b0=bounds[0], b1=bounds[1])) ax2.legend() for ax in [ax1, ax2]: ax.set_xlim([0, 1000]) # checksave if save: outputfolder = pathnames()['spectralplots'] + 'durations/PAPEROUT' fid = 'wav_{e}_{c}_{b0}_{b1}.png'.format(e=event_id, c=code, b0=bounds[0], b1=bounds[1]) fidout = os.path.join(outputfolder, fid) plt.savefig(fidout, dpi=plt.gcf().dpi) if show: plt.show() plt.close() return duration
def generate_duration_map(corners, event_id, show=True, save=False): """initiate and populate a basemap object for New Zealands north island. Functionality to manually ignore stations based on user quality control Takes station coordinates and coloring from npz files Choice to annotate two stations which correspond to waveforms Calls beachball and trench tracer to populate basemap :type corners: list of floats :param corners: values for map corners to set bounds e.g. [lat_bot,lat_top,lon_left,lon_right] """ manual_ignore_dict = { "2014p864702": ["LOBS1", "LOBS4"], "2014p715167": ["EBPR-3", "RTZ", "SBPR-1", "SBPR-2", "SBPR-3", "WSRZ"], "2016p859524": [], "2015p768477": ["BFZ"], "2014p051675": ["BFZ", "MRZ", "TSZ"], "2015p822263": ["TLZ", "BFZ", "RTZ"], "2014p240655": [ "ETVZ", "RTZ", ] } manual_ignore = manual_ignore_dict[event_id] f, m = mapmod.initiate_basemap(map_corners=corners, draw_lines=False) # load in duration values npzfolder = pathnames()['data'] + 'DURATIONS' stationfile = '{e}_{b0}_{b1}_durations.npz'.format(e=event_id, b0=bounds[0], b1=bounds[1]) sta = np.load(os.path.join(npzfolder, stationfile)) # manual ignorance names, lats, lons, durs = sta['NAME'], sta['LAT'], sta['LON'], sta[ 'DURATION'] for MI in manual_ignore: if MI in names: ind = np.where(names == MI)[0][0] names = np.delete(names, ind) lats = np.delete(lats, ind) lons = np.delete(lons, ind) durs = np.delete(durs, ind) # set colormap to the values of duration vmax = myround(np.nanmax(durs), base=50, choice='up') vmin = myround(np.nanmin(durs), base=50, choice='down') norm = mpl.colors.Normalize(vmin=vmin, vmax=vmax) cmap = cm.jet colormap = cm.ScalarMappable(norm=norm, cmap=cmap) # plot individual stations with color and zorder set by duration length for i, D in enumerate(durs): if np.isnan(D): continue color = 'w' D = 10 else: color = colormap.to_rgba(durs[i]) X, Y = m(lons[i], lats[i]) m.scatter(X, Y, marker='v', color=color, s=100, linewidth=1.1, edgecolor='k', zorder=int(D)) # fine tuned annotations """annotation dictionary 2014p051675 HAZ yshift=.0035 xshift=.0125, PUZ yshift=-.0255 xshift=-.05 2015p768477 TOZ yshift=.01 xshift=.01, KU15-3 yshift=-.0255 xshift=-.075 2014p715167 OPRZ yshift=.01 xshift=.01 , PUZ yshift=.015 xshift=-.05 2014p240655 MXZ yshift=.01 xshift=.01, MKAZ yshift=-.025,xshift=-.05 2014p864702 MXZ yshift=.01 xshift=.015, EBPR-2 yshift=.005, xshift=.015 """ ano = { "2014p051675": ["HAZ", .0035, .0125, "PUZ", -.0255, -.05], "2015p768477": ["TOZ", .01, .01, "KU15-3", -.0255, -.075], "2014p864702": ["MXZ", .01, .015, "EBPR-2", .005, .015], "2015p822263": ["MRZ", .01, .015, "PUZ", -.0255, 0.015], "2014p240655": ["MXZ", .01, .015, "MKAZ", -.025, -.05] } STA1 = ano[event_id][0] STA2 = ano[event_id][3] if (names[i] == STA1) or (names[i] == STA2): if names[i] == STA1: yshift = ano[event_id][1] * (m.ymax - m.ymin) xshift = ano[event_id][2] * (m.xmax - m.xmin) elif names[i] == STA2: yshift = ano[event_id][4] * (m.ymax - m.ymin) xshift = ano[event_id][5] * (m.xmax - m.xmin) plt.annotate(names[i], xy=(X, Y), xytext=(X + xshift, Y + yshift), fontsize=10, zorder=1000, weight='bold') # plt.annotate(names[i], # xy=(X,Y), # xytext=(X,Y), # fontsize=10, # zorder=1000, # weight='bold') plt.annotate( "(depth: 21 km)\n(depth: 14 km)\n(depth: 20 km)\n(depth: 60 km)\n(depth: 19 km)", xy=(X, Y + 0.02 * (m.ymax - m.ymin)), fontsize=8, zorder=1000, weight='bold') # additional map objects trace_trench(m) event_beachball_durationmap(event_id, m, anno=True) # m.drawmapscale(179.65,-41.75, 179.65,-41.75, 100,yoffset=0.01*(m.ymax-m.ymin)) m.drawmapscale(179, -41.75, 179, -41.75, 100, yoffset=0.01 * (m.ymax - m.ymin)) # colorbar colormap.set_array(durs) cbar = f.colorbar(colormap, fraction=0.046, pad=0.04) cbar.set_label('duration (s)', rotation=270, labelpad=17, fontsize=14.5) # plt.title(event_id) if save: outputfolder = pathnames()['spectralplots'] + 'durations/PAPEROUT' fid = 'map_{e}_{b0}_{b1}.png'.format(e=event_id, b0=bounds[0], b1=bounds[1]) fidout = os.path.join(outputfolder, fid) plt.savefig(fidout, dpi=plt.gcf().dpi) if show: plt.show()
def data_gather_and_process(code_set, pre_filt=None, night=False): """grab relevant data files for instrument code, process using internal functions, return arrays containing filtered waveforms and ratio values :type code_set: str :param code_set: instrument code set in main :type pre_filt: list of two floats :param pre_filt: [lower bound, upper bound] filter bounds for wavform plot :type night: bool :param night: if only night time considered, all files have '_night' suffix :rtype st_proc: obspy stream :return st_proc: processed stream object for plotting :rtype TEORRm: list of numpy arrays :return TEORRm: arrays containing filtered waveforms and amp. ratios """ # datapaths net, sta, loc, cha, d, year, jday = code_set.split('.') fid_path = pathnames()['beacon'] + "{y}/XX/{s}/HH{c}.D".format( y=year, s=sta, c="{c}") inv_path = pathnames()['beacon'] + "DATALESS/XX.RDF.DATALESS" # check what combination of files are available, process accordingly path_dict = check_save(code_set, night=night) process_check = False if not path_dict["npz"]: if not path_dict["pickle"]: if verbose: print("[files don't exist, processing...]") st = Stream() inv = read_inventory(inv_path) for comp in ["N", "E"]: fid = os.path.join(fid_path, code_set).format(c=comp) st += read(fid) if len(st) != 2: print("\t--too many ({}) traces found...".format(len(st))) return None, None else: if verbose: print("[stream exists, creating TEROR...]") inv = None process_check = True st = read(path_dict['pickle']) # create passband filtered arrays using internal functions st_proc, TEORRm = create_modified_TEROR( st, inv, night=night, already_preprocessed=process_check) if not st_proc: print("\t--stream not found...") return None, None check_bool = check_save(code_set, st=st_proc, TEORRm=TEORRm, night=night) if not check_bool: return None, None else: if verbose: print("[files exist, reading...]") st_proc = read(path_dict['pickle']) TEORRm = np.load(path_dict['npz']) return st_proc, TEORRm
def gridspec_plot(code, x, N, E, **options): """based on stacked_plot, but with gridspec changing size of subplots: multiple stations plotted in a stacked plot to show waveform coherence sts should be a stream of all components gridspec_plot(code=code_set,x=t,N=y_N_list,E=y_E_list, TEORRm_list=TEROR_list, sig_list=sig_list, ano_list=ano_NE_list, tremor_list=tremor_list, night=night, show=True, save=False) """ net, sta, loc, cha, d, year, jday = code.split('.') # initiate figure and axes objects f = plt.figure(figsize=(11.69, 8.27), dpi=75) gs = gridspec.GridSpec(5, 1, height_ratios=[2, 2, 1, 1, 1], hspace=0.2) ax1 = plt.subplot(gs[0]) ax2 = plt.subplot(gs[1], sharex=ax1) ax3a = plt.subplot(gs[2], sharex=ax1) ax3b = plt.subplot(gs[3], sharex=ax1) ax3c = plt.subplot(gs[4], sharex=ax1) for ax in [ax1, ax2, ax3a, ax3b]: plt.setp(ax.get_xticklabels(), visible=False) # create t axis to match x TEORRm_ = options['TEORRm_list'][0] x_Rm = np.linspace(x.min(), x.max(), len(TEORRm_['Rm'])) x_Rs = np.linspace(x.min(), x.max(), len(TEORRm_['Rs'])) x_Rh = np.linspace(x.min(), x.max(), len(TEORRm_['Rh'])) step_up = 0 n_ano, e_ano = options['ano_list'] for N_, E_, T_, TEROR_, TREMOR_, Nano_, Eano_ in zip( N, E, options['tremor_list'], options['TEORRm_list'], options['sig_list'], n_ano, e_ano): # amplitude ratios Rs_ = TEROR_['Rs'] Rm_ = TEROR_['Rm'] Rh_ = TEROR_['Rh'] # scatterpoints for values about two-sigma Rs_sigma_ = TREMOR_['Rs'] Rm_sigma_ = TREMOR_['Rm'] Rh_sigma_ = TREMOR_['Rh'] # shifting waveform plots up by increments N_ += step_up E_ += step_up T_ += step_up # waveforms ax1.plot(x, N_) ax1.plot(x, T_, 'k') ax2.plot(x, E_) ax2.plot(x, T_, 'k') # ratios ax3a.plot(x_Rs, Rs_, '|-', markersize=0.25) ax3b.plot(x_Rm, Rm_, '|-', markersize=1.25) ax3c.plot(x_Rh, Rh_, '|-', markersize=1.25) # two-sigmas ax3a.scatter(x_Rs, Rs_sigma_, marker='o', s=1.5, zorder=10) ax3b.scatter(x_Rm, Rm_sigma_, marker='o', s=4, zorder=10) ax3c.scatter(x_Rh, Rh_sigma_, marker='o', s=4, zorder=10) # annotations for ax, ano in zip([ax1, ax2], [Nano_, Eano_]): ax.annotate(ano, xy=(x.min(), step_up), xytext=(x.min(), step_up), fontsize=8, zorder=11) step_up += 0.5 # labelliung title = ("[Tremor Detection]\n" "Jday: {} Bandpass: [2-5Hz] Norm: 0-1 Cutoff: 0.5".format(jday)) ax1.set_title(title) ax1.set_ylabel('N. velocity (-1/1 norm)') ax2.set_ylabel('E. velocity (-1/1 norm)') ax3a.set_ylabel('5-sec. ratio (R$_s$)') ax3b.set_ylabel('5-min. ratio (R$_m$)') ax3c.set_ylabel('1-hour ratio (R$_h$)') ax3c.set_xlabel('NZ local time (hours)') # axis options # ax3.legend(prop={"size":7.5}) for ax in [ax1, ax2, ax3a, ax3b, ax3c]: pretty_grids(ax) # ax.set_xlim([18,30]) if night else ax.set_xlim([x.min(),x.max()]) ax.set_xlim([x.min(), x.max()]) # plt.tight_layout() if options['save']: fig_path = pathnames()['plots'] + 'tremor/' fig_name = code.format(c='?') + '.png' fig_out = os.path.join(fig_path, fig_name) plt.savefig(fig_out, dpi=200) if options['show']: plt.show() plt.close() def create_min_max(tr, pixel_length=10): """ Creates new data using a min/max approach that calculated the minimum and maximum values of each "pixel". Much faster plotting of large datasets. !!! base code copied and modified !!! from obspy.imaging.waveform.__plot_min_max """ # Some variables to help calculate the values. starttime = date2num(tr.stats.starttime.datetime) endtime = date2num(tr.stats.endtime.datetime) # The same trace will always have the same sampling_rate. sampling_rate = tr.stats.sampling_rate # width of x axis in seconds x_width = endtime - starttime # number of samples that get represented by one min-max pair # width = 800 # guessing # pixel_length = int( # np.ceil((x_width * sampling_rate + 1) / width)) # Loop over all the traces. Do not merge them as there are many samples # and therefore merging would be slow. trace_length = len(tr.data) pixel_count = int(trace_length // pixel_length) remaining_samples = int(trace_length % pixel_length) remaining_seconds = remaining_samples / sampling_rate # Reference to new data array which does not copy data but can be # reshaped. if remaining_samples: data = tr.data[:-remaining_samples] else: data = tr.data data = data.reshape(pixel_count, pixel_length) min_ = data.min(axis=1) * tr.stats.calib max_ = data.max(axis=1) * tr.stats.calib # Calculate extreme_values and put them into new array. if remaining_samples: extreme_values = np.empty((pixel_count + 1, 2), dtype=np.float) extreme_values[:-1, 0] = min_ extreme_values[:-1, 1] = max_ extreme_values[-1, 0] = \ tr.data[-remaining_samples:].min() * tr.stats.calib extreme_values[-1, 1] = \ tr.data[-remaining_samples:].max() * tr.stats.calib else: extreme_values = np.empty((pixel_count, 2), dtype=np.float) extreme_values[:, 0] = min_ extreme_values[:, 1] = max_ # Finally plot the data. start = date2num(tr.stats.starttime.datetime) end = date2num(tr.stats.endtime.datetime) if remaining_samples: # the last minmax pair is inconsistent regarding x-spacing x_values = np.linspace(start, end - remaining_seconds, num=extreme_values.shape[0] - 1) x_values = np.concatenate([x_values, [end]]) else: x_values = np.linspace(start, end, num=extreme_values.shape[0]) x_values = np.repeat(x_values, 2) y_values = extreme_values.flatten() return x_values, y_values
def plot_arrays(st, code_set, TEORRm, sig, show=True, save=False): """plot 6 streams in 3 subplot figure """ f, (ax1, ax2, ax3) = plt.subplots(3, sharex=True, sharey=False, figsize=(11.69, 8.27), dpi=200) # divy out arrays T, E, O, R, Rm = TEORRm sig2, sig3 = sig # create time axis stats = st[0].stats start = stats.starttime end = stats.endtime tracelength = (end - start) / 3600 t = np.linspace(0, tracelength, len(R)) tRm = np.linspace(0, tracelength, len(Rm)) # full waveforms A1 = ax1.plot(t, st[0].data, color='orange', label=st[0].get_id()) A2 = ax1.plot(t, st[1].data, color='b', label=st[1].get_id()) # filtered waveforms # B1 = ax2.plot(t,T,color='k',label="[T]remor Band 2-8Hz") # B2 = ax2.plot(t,E,color='r',label="[E]arthquake Band 10-20Hz") # B3 = ax2.plot(t,O,color='g',label="[O]cean Band .5-1Hz") B4 = ax2.plot(t, R, color='c', label="[R]atio") # amplitude ratio and median value # C1 = ax3.plot(t,R,color='k',label='Amplitude [R]atio (T^2/(E*O))') C2 = ax3.plot(tRm, Rm, color='k', label='Amplitude [R]atio [m]edian', linewidth=1, zorder=4) C3 = ax3.scatter(tRm, __z2nan(sig2), c='r', marker='^', zorder=5, label='2-sigma', s=4) C4 = ax3.scatter(tRm, __z2nan(sig3), c='orange', marker='o', zorder=6, label='3-sigma') # plot vertical lines on each subplot for tremor locations for X, Y2 in zip(tRm, sig2): if np.isnan(Y2): continue else: for ax in [ax1, ax2, ax3]: D2 = ax.axvline(X, zorder=1, linestyle="solid", color='gray', linewidth=1, alpha=0.35) # set axis properties for ax in [ax1, ax2, ax3]: pretty_grids(ax) ax.legend(prop={"size": 7.5}) ax1.set_xlim([t.min(), t.max()]) st_std = 5 * np.std(st[0].data) # ax1.set_ylim([-st_std,st_std]) ax3.set_ylim([Rm.min(), Rm.max()]) # ax2.set_yscale("log") ax1.set_title("TEROR {}".format(code_set)) ax1.set_ylabel("velocity (m/s)") ax2.set_ylabel("velocity (m/s)") ax3.set_ylabel("dimensionless") ax3.set_xlabel("time (hours from UTC midnight)") plt.tight_layout() if show: plt.show() if save: fig_path = pathnames()['plots'] + 'tremor/' fig_name = code_set.format(c='?') + '.png' fig_out = os.path.join(fig_path, fig_name) plt.savefig(fig_out) return f
def envelope_plots(code, x, N, E, **options): """based on stacked_plot, but with gridspec changing size of subplots: multiple stations plotted in a stacked plot to show waveform coherence sts should be a stream of all components """ net, sta, loc, cha, d, year, jday = code.split('.') # initiate figure and axes objects f = plt.figure(figsize=(11.69, 8.27), dpi=75) gs = gridspec.GridSpec(6, 1, height_ratios=[2, 2, 2, 1, 1, 1], hspace=0.2) ax1 = plt.subplot(gs[0]) ax2 = plt.subplot(gs[1], sharex=ax1) ax2a = plt.subplot(gs[2], sharex=ax1) ax3a = plt.subplot(gs[3], sharex=ax1) ax3b = plt.subplot(gs[4], sharex=ax1) ax3c = plt.subplot(gs[5], sharex=ax1) for ax in [ax1, ax2, ax3a, ax3b]: plt.setp(ax.get_xticklabels(), visible=False) # create t axis to match x TEORRm_ = options['TEORRm_list'][0] x_Rm = np.linspace(x.min(), x.max(), len(TEORRm_['Rm'])) x_Rs = np.linspace(x.min(), x.max(), len(TEORRm_['Rs'])) x_Rh = np.linspace(x.min(), x.max(), len(TEORRm_['Rh'])) x_Env = np.linspace(x.min(), x.max(), len(options['envelopes'][0])) x_sur = np.linspace(x.min(), x.max(), len(options['surface'])) step_up = 0 n_ano, e_ano = options['ano_list'] for N_, E_, Env_, TEROR_, TREMOR_, Nano_, Eano_ in zip( N, E, options['envelopes'], options['TEORRm_list'], options['sig_list'], n_ano, e_ano): # amplitude ratios Rs_ = TEROR_['Rs'] Rm_ = TEROR_['Rm'] Rh_ = TEROR_['Rh'] # scatterpoints for values about two-sigma Rs_sigma_ = TREMOR_['Rs'] Rm_sigma_ = TREMOR_['Rm'] Rh_sigma_ = TREMOR_['Rh'] # shifting waveform plots up by increments N_ += step_up # Env_ += step_up # waveforms ax1.plot(x, N_) ax2.plot(x_Env, Env_) # ratios ax3a.plot(x_Rs, Rs_, '|-', markersize=0.25) ax3b.plot(x_Rm, Rm_, '|-', markersize=1.25) ax3c.plot(x_Rh, Rh_, '|-', markersize=1.25) # two-sigmas ax3a.scatter(x_Rs, Rs_sigma_, marker='o', s=1.5, zorder=10) ax3b.scatter(x_Rm, Rm_sigma_, marker='o', s=4, zorder=10) ax3c.scatter(x_Rh, Rh_sigma_, marker='o', s=4, zorder=10) # annotations for ax, ano in zip([ax1, ax2], [Nano_, Eano_]): ax.annotate(ano, xy=(x.min(), step_up), xytext=(x.min(), step_up), fontsize=8, zorder=11) step_up += 0.5 ax2a.plot(x_sur, options['surface'], 'k') # labelliung title = ("[Tremor Detection]\n" "Jday: {} Bandpass: [2-5Hz] Norm: 0-1 Cutoff: 0.5".format(jday)) ax1.set_title(title) ax1.set_ylabel('N. velocity (-1/1 norm)') ax2.set_ylabel('Waveform Envelopes') ax2a.set_ylabel("N. Velocity (m/s) [6-30s]") ax3a.set_ylabel('5-sec. ratio (R$_s$)') ax3b.set_ylabel('5-min. ratio (R$_m$)') ax3c.set_ylabel('1-hour ratio (R$_h$)') ax3c.set_xlabel('NZ local time (hours)') # axis options # ax3.legend(prop={"size":7.5}) for ax in [ax1, ax2, ax2a, ax3a, ax3b, ax3c]: pretty_grids(ax) # ax.set_xlim([18,30]) if night else ax.set_xlim([x.min(),x.max()]) ax.set_xlim([x.min(), x.max()]) # plt.tight_layout() if options['save']: fig_path = pathnames()['plots'] + 'tremor/' fig_name = code.format(c='?') + '.png' fig_out = os.path.join(fig_path, fig_name) plt.savefig(fig_out, dpi=200) if options['show']: plt.show() plt.close()