def main(data_dir, output_dir): # Get borehole geode info stats = pd.read_csv("walkaround_borehole_orientation_stats.csv") # Loop over stations/geodes for sta in ['BH001', 'BH002', 'BH004', 'BH005', 'BH006', 'BH008', 'BH011', 'BH012', 'BH013', 'BH014', 'BH015', 'BH016', 'BH017', 'BH018']: # geodes.Geode: print("Processing station %s" % sta) # Rotation matrix for correction inc_corr = - stats.loc[stats['geode'] == sta, 'inclination'].values[0] baz_corr = - stats.loc[stats['geode'] == sta, 'mean'].values[0] # Read data flist1 = glob(os.path.join(data_dir, "8O.%s..DP1*" % sta)) flist2 = glob(os.path.join(data_dir, "8O.%s..DP2*" % sta)) flist3 = glob(os.path.join(data_dir, "8O.%s..DP3*" % sta)) if not flist1 or not flist2 or not flist3: continue # Look for suffix file = os.path.split(flist1[0])[1] if file.find("unit") != -1: idx = file.find("unit") suffix = "_" + file[idx:].split(".")[0] else: suffix = "" st = Stream() st += read(os.path.join(data_dir, "8O.%s..DP1*" % sta), format="SAC")[0] st += read(os.path.join(data_dir, "8O.%s..DP2*" % sta), format="SAC")[0] st += read(os.path.join(data_dir, "8O.%s..DP3*" % sta), format="SAC")[0] if len(st) == 0: continue st.resample(500.0) starttime = st[0].stats.starttime endtime = st[0].stats.endtime # Save rotated coordinates st3 = st.copy() compN, compE, compZ = rotate_to_zne(st3[0].data, st3[1].data, st3[2].data, inc_corr, baz_corr) trN = SACTrace.from_obspy_trace(st3[0]) trN.data = compN trN.kcmpnm = "DPN" trN.write(os.path.join(output_dir, "8O.%s..DPN.%s_%s%s.sac" % (sta, starttime.strftime("%Y%m%d%H%M%S"), endtime.strftime("%Y%m%d%H%M%S"), suffix))) trE = SACTrace.from_obspy_trace(st3[1]) trE.data = compE trE.kcmpnm = "DPE" trE.write(os.path.join(output_dir, "8O.%s..DPE.%s_%s%s.sac" % (sta, starttime.strftime("%Y%m%d%H%M%S"), endtime.strftime("%Y%m%d%H%M%S"), suffix))) trZ = SACTrace.from_obspy_trace(st3[2]) trZ.data = compZ trZ.kcmpnm = "DPZ" trZ.write(os.path.join(output_dir, "8O.%s..DPZ.%s_%s%s.sac" % (sta, starttime.strftime("%Y%m%d%H%M%S"), endtime.strftime("%Y%m%d%H%M%S"), suffix)))
def saverf(self, path, evtstr=None, phase='P', shift=0, evla=-12345., evlo=-12345., evdp=-12345., mag=-12345., gauss=0, baz=-12345., gcarc=-12345., only_r=False, **kwargs): if phase == 'P': if only_r: loop_lst = [1] else: loop_lst = [0, 1] rayp = seispy.geo.srad2skm(self.PArrival.ray_param) elif phase == 'S': loop_lst = [2] rayp = seispy.geo.srad2skm(self.SArrival.ray_param) else: raise ValueError('Phase must be in \'P\' or \'S\'') if evtstr is None: filename = join(path, self.datestr) else: filename = join(path, evtstr) for i in loop_lst: header = {'evla': evla, 'evlo': evlo, 'evdp': evdp, 'mag': mag, 'baz': baz, 'gcarc': gcarc, 'user0': rayp, 'kuser0': 'Ray Para', 'user1': gauss, 'kuser1': 'G factor'} for key in kwargs: header[key] = kwargs[key] for key, value in header.items(): self.rf[i].stats['sac'][key] = value tr = SACTrace.from_obspy_trace(self.rf[i]) tr.b = -shift tr.o = 0 tr.write(filename + '_{0}_{1}.sac'.format(phase, tr.kcmpnm[-1]))
def theoretical_arrival(tr, modelname="prem", phase_list=["P"]): """Get predicted phase arrival based the SAC trace Parameter ========= tr : obspy.trace obspy trace read from SAC file modelname : str model name phase_list : list phase list to get arrivals """ # ------------------------------------------------------------------------- # construct the origin time # ------------------------------------------------------------------------- sactr = SACTrace.from_obspy_trace(tr) evdp, gcarc = sactr.evdp, sactr.gcarc # ------------------------------------------------------------------------- # get waveforms of P and S wave based on given 1D model and time shift # ------------------------------------------------------------------------- model = TauPyModel(model=modelname) arr = model.get_travel_times(source_depth_in_km = evdp / 1000, distance_in_degree = gcarc, phase_list=phase_list) return sactr.reftime, arr
def Bandpass(datapath): # for j in tqdm(range(10),desc = "prosessing"): filepath = datapath + "/predict/syn/Z/" overpath = datapath + "/predict/syn/Z/" os.chdir(filepath) for i in range(300): st = obspy.read(filepath + str(i) + '.sac') tr = st[0] tr.filter('bandpass', freqmin=8, freqmax=15, corners=4, zerophase=True) # tr.filter('highpass', freq=8, corners=4, zerophase=True) tr = (tr.data) / np.max(abs(tr.data)) sacfile = Trace() sacfile.data = tr[:] sac = SACTrace.from_obspy_trace(sacfile) sac_data = sac.data sac.stla = 35 sac.stlo = 110 + (80 + 72 * 500 + i * 25) / 111000 sac.delta = 0.0006 sac.evla = 35 sac.evlo = 110 + (6568 + 500 * 72) / 111000 sac.evdp = 0.05 sac.write(overpath + str(72 * 520 + i) + ".sac")
def saverf(self, path, evtstr=None, shift=0, evla=-12345., evlo=-12345., evdp=-12345., mag=-12345., gauss=0, baz=-12345., gcarc=-12345., only_r=False, **kwargs): if self.phase[-1] == 'P': if self.comp == 'lqt': svcomp = 'Q' else: svcomp = 'R' if only_r: loop_lst = [svcomp] else: loop_lst = [svcomp, 'T'] rayp = srad2skm(self.rayp) elif self.phase[-1] == 'S': if self.comp == 'lqt': loop_lst = ['L'] else: loop_lst = ['Z'] rayp = srad2skm(self.rayp) else: pass if evtstr is None: filename = join(path, self.datestr) else: filename = join(path, evtstr) for comp in loop_lst: trrf = self.rf.select(channel='*' + comp)[0] header = { 'evla': evla, 'evlo': evlo, 'evdp': evdp, 'mag': mag, 'baz': baz, 'gcarc': gcarc, 'user0': rayp, 'kuser0': 'Ray Para', 'user1': gauss, 'kuser1': 'G factor' } for key in kwargs: header[key] = kwargs[key] for key, value in header.items(): trrf.stats['sac'][key] = value tr = SACTrace.from_obspy_trace(trrf) tr.b = -shift tr.a = 0 tr.ka = self.phase tr.write(filename + '_{0}_{1}.sac'.format(self.phase, tr.kcmpnm[-1]))
def test_sac_booleans_from_trace(self): """ SAC booleans "lcalda" and "lpspol" should be "False" and "True", respectively, by default when converting from a "Trace". """ tr = Trace() sac = SACTrace.from_obspy_trace(tr) self.assertFalse(sac.lcalda) self.assertTrue(sac.lpspol)
def make_sac_trace(data_block, sac_header, data_length): from obspy.io.sac import SACTrace flatten_data = np.concatenate(data_block[..., 15::]) sac_header.npts = flatten_data.size new_trace = Trace(data=flatten_data, header=sac_header) sac_trace = SACTrace.from_obspy_trace(new_trace) sac_trace.stla = sac_header.stla sac_trace.stlo = sac_header.stlo sac_trace.stel = sac_header.stel if int(new_trace.stats.npts % data_length) is not 0: raise AttributeError("data format error!") else: return sac_trace
def update_traces(self): # AXITRA convention is x=north and y=east cmp = {'X': 'N', 'Y': 'E', 'Z': 'Z'} instr = {'velocity': 'H', 'displacement': 'H', 'acceleration': 'N'} idep = {'velocity': 7, 'displacement': 6, 'acceleration': 8} for n, station in enumerate(self.stations): stid = station.code.split('.') if len(stid) == 3: net, sta, loc = stid elif len(stid) == 2: net, sta = stid loc = None else: sta = '_'.join(stid) net = None loc = None filenames = 'axi{:03d}.?.sac'.format(n + 1) filenames = os.path.join(self.run_name, filenames) for fname in glob(filenames): tr = read(fname)[0] tr.stats.network = net tr.stats.station = sta tr.stats.location = loc sr = tr.stats.sampling_rate if sr < 10: band = 'L' elif 10 <= sr < 80: band = 'B' elif sr >= 80: band = 'H' channel = band + instr[self.output] + cmp[tr.stats.channel] tr.stats.channel = channel # Set SAC data type. Note that SAC data amplitude is in nm, # nm/s or nm/s/s, so we need to multiply by 1e9 # https://ds.iris.edu/files/sac-manual/manual/file_format.html tr.data *= 1e9 tr.stats.sac.idep = idep[self.output] tr.stats.sac.stla = station.lat tr.stats.sac.stlo = station.lon tr.stats.sac.stel = -station.z sac = SACTrace.from_obspy_trace(tr) sac.reftime = self.min_origin_time + self.trace_start_offset sac.b = 0 outfile = tr.id + '.sac' outfile = os.path.join(self.run_name, outfile) sac.write(outfile) os.remove(fname)
def update_traces(self): # AXITRA convention is x=north and y=east cmp = {'X': 'N', 'Y': 'E', 'Z': 'Z'} instr = {'velocity': 'H', 'displacement': 'H', 'acceleration': 'N'} for n, station in enumerate(self.stations): stid = station.code.split('.') if len(stid) == 3: net, sta, loc = stid elif len(stid) == 2: net, sta = stid loc = None else: sta = '_'.join(stid) net = None loc = None filenames = 'axi{:03d}.?.sac'.format(n+1) filenames = os.path.join(self.run_name, filenames) for fname in glob(filenames): tr = read(fname)[0] tr.stats.network = net tr.stats.station = sta tr.stats.location = loc sr = tr.stats.sampling_rate if sr < 10: band = 'L' elif 10 <= sr < 80: band = 'B' elif sr >= 80: band = 'H' channel = band + instr[self.output] + cmp[tr.stats.channel] tr.stats.channel = channel tr.stats.sac.stla = station.lat tr.stats.sac.stlo = station.lon tr.stats.sac.stel = -station.z sac = SACTrace.from_obspy_trace(tr) sac.reftime = self.min_origin_time+self.trace_start_offset sac.b = 0 outfile = tr.id + '.sac' outfile = os.path.join(self.run_name, outfile) sac.write(outfile) os.remove(fname)
# st.remove_response(output="DISP", zero_mean=True, taper=True, taper_fraction=0.05, pre_filt=[0.001, 0.005, sr/3, sr/2], water_level=60) # Downsample st.detrend(type='demean') st.detrend(type='linear') st.filter('lowpass', freq=0.4 * sr_new, zerophase=True) # anti-alias filter st.filter('highpass', freq=1 / 60 / 60, zerophase=True) # Remove daily oscillations st.decimate(factor=int(sr / sr_new), no_filter=True) # downsample st.taper(type="cosine", max_percentage=0.05) st.detrend(type='demean') st.detrend(type='linear') # convert to SAC and fill out station/event header info sac = SACTrace.from_obspy_trace(st[0]) sac.stel = staz[ista] sac.stla = stala[ista] sac.stlo = stalo[ista] kcmpnm = comp sac.kcmpnm = kcmpnm yr = str(st[0].stats.starttime.year) jday = '%03i' % (st[0].stats.starttime.julday) hr = '%02i' % (st[0].stats.starttime.hour) mn = '%02i' % (st[0].stats.starttime.minute) sec = '%02i' % (st[0].stats.starttime.second) sac_out = path2sac + sta + '/' + sta + '.' + yr + '.' + jday + '.' + hr + '.' + mn + '.' + sec + '.' + kcmpnm + '.sac' sac.write(sac_out) # %% codecell # sta = "CC04"
st_bhr.stats.channel = Rcomp st_bhr.data = r # Remove existing file if os.path.exists(evdir + event+'.'+network+'.'+str(sta)+'.'+Ncomp+'.sac'): os.remove(evdir + event+'.'+network+'.'+str(sta)+'.'+Ncomp+'.sac') if os.path.exists(evdir + event+'.'+network+'.'+str(sta)+'.'+Ecomp+'.sac'): os.remove(evdir + event+'.'+network+'.'+str(sta)+'.'+Ecomp+'.sac') if os.path.exists(evdir + event+'.'+network+'.'+str(sta)+'.'+Tcomp+'.sac'): os.remove(evdir + event+'.'+network+'.'+str(sta)+'.'+Tcomp+'.sac') if os.path.exists(evdir + event+'.'+network+'.'+str(sta)+'.'+Rcomp+'.sac'): os.remove(evdir + event+'.'+network+'.'+str(sta)+'.'+Rcomp+'.sac') network = st_bhr.stats.network # Save BHN, BHE, BHR, and BHT sac_n = SACTrace.from_obspy_trace(st_bhn) sac_n.write(evdir + event+'.'+network+'.'+str(sta)+'.'+Ncomp+'.sac') sac_e = SACTrace.from_obspy_trace(st_bhe) sac_e.write(evdir + event+'.'+network+'.'+str(sta)+'.'+Ecomp+'.sac') sac_t = SACTrace.from_obspy_trace(st_bht) sac_t.write(evdir + event+'.'+network+'.'+str(sta)+'.'+Tcomp+'.sac') sac_r = SACTrace.from_obspy_trace(st_bhr) sac_r.write(evdir + event+'.'+network+'.'+str(sta)+'.'+Rcomp+'.sac') # fmin = 1/100 # fmax = 1/20 # st_bht.filter("bandpass", freqmin=fmin, freqmax=fmax, corners=2, zerophase=True) # st_bhr.filter("bandpass", freqmin=fmin, freqmax=fmax, corners=2, zerophase=True) # plt.figure(figsize=(10,5)) # plt.plot(np.arange(0,len(r)), st_bht.data, color="red") # plt.plot(np.arange(0,len(t)), st_bhr.data, color="black")
def process_seg2(flist, cha_list, outdir, day): """ Given a list of 30-s long SEG2 files, merge into one file per channel, decimate to 100 Hz and write as SAC""" # Create output directory with name of date for start time day_dir = os.path.join(outdir, day) if not os.path.exists(day_dir): os.mkdir(day_dir) # Loop over channels for channel in cha_list: sta, comp, dep = get_station_component(channel) print("Assembling data for channel %d: geode %s, component %s, depth %f m" % (channel, sta, comp, dep)) # if glob(os.path.join(day_dir, "8O.%s..%s.*.sac" % (sta, comp))): # print("Station %s already processed." % sta) # continue # Initialize a Stream object st = Stream() # Loop over 30-s long files and append data for file in sorted(flist): tmp = read(file, format="SEG2") if not tmp: raise ValueError("Data file read is empty: %s" % file) trace = [] for tr in tmp: if int(tr.stats.seg2.CHANNEL_NUMBER) == channel: # Check for NaN if np.isnan(tr.data).any(): print("There are NaN values in this file: %s" % file) idx_nan = np.argwhere(np.isnan(tr.data)) # Replace by 0 tr.data[idx_nan] = 0 print("Replaced %d samples by 0." % len(idx_nan)) continue trace = tr # correct start_time for SEG-2 acquisition delay trace.stats.starttime = tr.stats.starttime + float(tr.stats.seg2.DELAY) # correct amplitude for amplifier-gain amp_gain = float(tr.stats.seg2.FIXED_GAIN.split(" ")[0]) instrument_correction_scalar = SENSITIVITY * (10.**(amp_gain/20)) # See 7.7 from Eaton 2018 trace.data = trace.data * float(tr.stats.seg2.DESCALING_FACTOR)/float(tr.stats.seg2.STACK) * 1e-3 # convert to Volt trace.data = trace.data / instrument_correction_scalar break if not trace: print("Could not find data for this channel in file %s" % file) continue st.append(trace) st.merge(method=1, interpolation_samples=-1, fill_value=0) # Check stream has only one merged trace if len(st) == 0: raise ValueError("Something went wrong: no data found for channel %d" % channel) elif len(st) > 1: print(st) raise ValueError("Something went wrong: there should be only one trace in the stream.") # Resample to 500Hz #st.resample(500.0) # Check data for gaps if st.get_gaps(): st.print_gaps() warnings.warn("There are gaps in the data.") # Decimate data by factor of 5: from 500Hz to 100Hz #st.decimate(factor=5) # Cut day ts = UTCDateTime(int(day[0:4]),int(day[4:6]),int(day[6:]),0,0,0) te = ts + 3600*24 st.trim(starttime=ts,endtime=te) print(st) # Add header info sac = SACTrace.from_obspy_trace(st[0]) sac.kcmpnm = comp sac.kstnm = sta sac.stel = 779.60 # Ground elevation in m sac.stdp = dep sac.stla = 50.45031 # coordinates of geophysics well sac.stlo = -112.12087 # coordinates of geophysics well sac.knetwk = "8O" # give network code BH for "borehole" # Define output file name sacname = "8O.%s..%s.%s_%s_%dHz_unitmps.sac" % (sta, comp, st[0].stats.starttime.strftime("%Y%m%d%H%M%S"), st[0].stats.endtime.strftime("%Y%m%d%H%M%S"), int(st[0].stats.sampling_rate)) sac.write(os.path.join(day_dir, sacname))
def _writesac(self, stream, event, station, outdir): """ Write data with SAC format with event and station information. """ for trace in stream: # loop over 3-component traces # transfer obspy trace to sac trace sac_trace = SACTrace.from_obspy_trace(trace=trace) # set station related headers sac_trace.stla = station["stla"] sac_trace.stlo = station["stlo"] sac_trace.stel = station["stel"] if trace.stats.channel[-1] == "E": sac_trace.cmpaz = 90 sac_trace.cmpinc = 90 elif trace.stats.channel[-1] == "N": sac_trace.cmpaz = 0 sac_trace.cmpinc = 90 elif trace.stats.channel[-1] == "Z": sac_trace.cmpaz = 0 sac_trace.cmpinc = 0 else: logger.warning("Not E|N|Z component") # set event related headers sac_trace.evla = event["latitude"] sac_trace.evlo = event["longitude"] sac_trace.evdp = event["depth"] sac_trace.mag = event["magnitude"] # 1. SACTrace.from_obspy_trace automatically set Trace starttime # as the reference time of SACTrace, when converting Trace to # SACTrace. Thus in SACTrace, b = 0.0. # 2. Set SACTrace.o as the time difference in seconds between # event origin time and reference time (a.k.a. starttime). # 3. Set SACTrace.iztype to 'io' change the reference time to # event origin time (determined by SACTrace.o) and also # automatically change other time-related headers # (e.g. SACTrace.b). # 1.from_obspy_trace # o # | # b----------------------e # |=> shift <=| # reftime | # origin time # # 2.sac_trace.o = shift # o:reset to be zero # | # b---------------------e # | | # | refer(origin) time # -shift sac_trace.o = event["origin"] - sac_trace.reftime sac_trace.iztype = 'io' sac_trace.lcalda = True # SAC file location sac_flnm = ".".join([event["origin"].strftime("%Y.%j.%H.%M.%S"), "0000", trace.id, "M", "SAC"]) sac_fullname = os.path.join(outdir, sac_flnm) sac_trace.write(sac_fullname) return
def main(): args = get_args() if args.nickname[-3:] == 'ph5': ph5file = os.path.join(args.ph5path, args.nickname) else: ph5file = os.path.join(args.ph5path, args.nickname + '.ph5') args.nickname += '.ph5' if not os.path.exists(ph5file): LOGGER.error("{0} not found.\n".format(ph5file)) sys.exit(-1) ph5API_object = ph5api.PH5(path=args.ph5path, nickname=args.nickname) if args.array: args.array = args.array.split(',') if args.sta_id_list: args.sta_id_list = args.sta_id_list.split(',') if args.sta_list: args.sta_list = args.sta_list.split(',') if args.shotline: args.shotline = args.shotline.split(',') if args.eventnumbers: args.eventnumbers = args.eventnumbers.split(',') if args.sample_rate: args.sample_rate = args.sample_rate.split(',') if args.component: args.component = args.component.split(',') if args.channel: args.channel = args.channel.split(',') args.reqtype = args.reqtype.upper() args.format = args.format.upper() try: if args.reqtype != "SHOT" and args.reqtype != "FDSN" and \ args.reqtype != "RECEIVER": raise PH5toMSAPIError("Error - Invalid request type {0}. " "Choose from FDSN, SHOT, or RECEIVER." .format(args.reqtype)) if args.format != "MSEED" and args.format != "SAC": raise PH5toMSAPIError("Error - Invalid data format {0}. " "Choose from MSEED or SAC." .format(args.format)) ph5ms = PH5toMSeed(ph5API_object, out_dir=args.out_dir, reqtype=args.reqtype, netcode=args.network, station=args.sta_list, station_id=args.sta_id_list, channel=args.channel, component=args.component, array=args.array, shotline=args.shotline, eventnumbers=args.eventnumbers, length=args.length, starttime=args.start_time, stoptime=args.stop_time, offset=args.offset, das_sn=args.das_sn, use_deploy_pickup=args.deploy_pickup, decimation=args.decimation, sample_rate_keep=args.sample_rate, doy_keep=args.doy_keep, stream=args.stream, reduction_velocity=args.red_vel, notimecorrect=args.notimecorrect, format=args.format) for stream in ph5ms.process_all(): if args.format.upper() == "MSEED": if not args.non_standard: stream.write(ph5ms.filenamemseed_gen(stream), format='MSEED', reclen=4096) else: stream.write(ph5ms.filenamemseed_nongen(stream), format='MSEED', reclen=4096) elif args.format.upper() == "SAC": for trace in stream: sac = SACTrace.from_obspy_trace(trace) if not args.non_standard: sac.write(ph5ms.filenamesac_gen(trace)) else: sac.write(ph5ms.filenamesac_nongen(trace)) except PH5toMSAPIError as err: LOGGER.error("{0}".format(err.message)) exit(-1) ph5API_object.close()
from obspy.io.sac import SACTrace from obspy import UTCDateTime # ---- 01. Ask user for inputs --------------------------- if len(sys.argv) == 2: filename = sys.argv[1] else: print( "Please enter one variable i.e. Obspy2SAC 1991-01-01T01:19:46.930000Z_1991-01-01T01:26:02.760000Z.pk" ) sys.exit() # ---- 02. read in data Waveforms = read(filename) for wf in Waveforms: sac_trace = SACTrace.from_obspy_trace(wf) sac_reftime = sac_trace.reftime if "o" in wf.stats and wf.stats.o != UTCDateTime(-12345): sac_trace.o = wf.stats.o - sac_reftime if "t1" in wf.stats and wf.stats.t1 != UTCDateTime(-12345): sac_trace.t1 = wf.stats.t1 - sac_reftime if "t2" in wf.stats and wf.stats.t2 != UTCDateTime(-12345): sac_trace.t2 = wf.stats.t2 - sac_reftime if "evla" in wf.stats: sac_trace.evla = wf.stats.evla if "evlo" in wf.stats: sac_trace.evlo = wf.stats.evlo if "evdp" in wf.stats: sac_trace.evdp = wf.stats.evdp if "stla" in wf.stats: sac_trace.stla = wf.stats.stla
st.trim(starttime=tdbeg, endtime=tdend, pad=True, nearest_sample=False, fill_value=0) # make sure correct length st.detrend(type='demean') st.detrend(type='linear') st.taper(type="cosine",max_percentage=0.05) if is_downsamp and sr!=sr_new: st.filter('lowpass', freq=0.4*sr_new, zerophase=True) # anti-alias filter st.filter('highpass', freq=1/60/60, zerophase=True) # Remove daily oscillations st.decimate(factor=int(sr/sr_new), no_filter=True) # downsample st.detrend(type='demean') st.detrend(type='linear') st.taper(type="cosine",max_percentage=0.05) # convert to SAC and fill out station/event header info for tr in st: sac = SACTrace.from_obspy_trace(tr) sac.stel = inventory[0].stations[ista].elevation sac.stla = inventory[0].stations[ista].latitude sac.stlo = inventory[0].stations[ista].longitude kcmpnm = sac.kcmpnm yr = str(st[0].stats.starttime.year) jday = '%03i'%(st[0].stats.starttime.julday) hr = '%02i'%(st[0].stats.starttime.hour) mn = '%02i'%(st[0].stats.starttime.minute) sec = '%02i'%(st[0].stats.starttime.second) sac_out = stadir + '/' + station+'.'+yr+'.'+jday+'.'+hr+'.'+mn+'.'+sec+'.'+kcmpnm+'.sac' sac.write(sac_out)
def save_to_file(st, station_file, segy_filepath, output_dir): ''' Save trace to SAC file, filling header with station information :param st: Obspy stream with only one trace, the one to save :param station_file: station CSV filename (full path) with station info :param segy_filepath: SEGY filepath to find matching station information :param output_dir: output directory where to write SAC files. :return: ''' # Get station info station, stla, stlo, stel = get_station_info(segy_filepath, station_file=station_file) # Output directory for station raw_out_dir = output_dir + station + '/' if not os.path.exists(raw_out_dir): os.mkdir(raw_out_dir) # Correct for spikes (amplitudes ~ 1e20, in general > 1) trace = st[0] data = trace.data data[data > SPIKE_THRESHOLD] = 0 data[data < -SPIKE_THRESHOLD] = 0 # Correct for instrument response with a scalar (corrects for amplitudes above corner frequency) data = data / INSTRUMENT_CORRECTION_SCALAR # Convert amplitude to m/s trace.data = data # Create SAC trace sac = SACTrace.from_obspy_trace(trace) # Get channel name and orientation comp = trace.meta.segy.trace_header.trace_sequence_number_within_line if comp == 1: # Vertical channel channel = CHANNEL_CODE + 'Z' sac.cmpaz = 0 sac.cmpinc = 0 elif comp == 2: # Magnetic North-South channel = CHANNEL_CODE + '1' sac.cmpaz = LOCAL_DECLINATION sac.cmpinc = 90 elif comp == 3: # Magnetic East-West channel = CHANNEL_CODE + '2' sac.cmpaz = LOCAL_DECLINATION + 90 sac.cmpinc = 90 sac.kcmpnm = channel # Fill in header with other station info sac.kstnm = station sac.stla = stla sac.stlo = stlo sac.stel = stel sac.khole = "" sac.knetwk = NETWORK_CODE # Create output file name: tstart = trace.meta.starttime tend = trace.meta.endtime raw_fname = os.path.join( raw_out_dir, "{0}.{1}..{2}.D.{3}.{4}_unitmps.sac".format( NETWORK_CODE, station, channel, tstart.strftime("%Y%m%d.%H%M%S"), tend.strftime("%H%M%S"))) # Check if file already exists. If yes don't save if os.path.exists(raw_fname): print("%s already exists." % raw_fname) return # Now save SAC data to file print('Saving data to file: ' + raw_fname) sac.write(raw_fname)