Working with Waveforms
How to read and write waveforms.
Retrieving waves from a query
Waveforms are described in the
Wfdisc table, and there are two ways to get waveforms from a query.
Read directly from
If you have instances from the
Wfdisc class, you can easily convert them to ObsPy
instances for analysis or plotting. Pisces Wfdisc class instances have a
Trace instance from the
Wfdisc instance. Alternately, you can use the
wfdisc2trace function on a vanilla SQLAlchemy Wfdisc instance (no
Finally, you can use the low-level function
read_waveform, which underlies all the methods above.
This function returns a raw NumPy array instead of an Obspy Trace, however.
from mytables import Wfdisc from pisces import wfdisc2trace, read_waveform # loop over 10 BHZ wfdisc instances from the database for wf in session.query(Wfdisc).filter(Wfdisc.chan == 'BHZ').limit(10): # the following two traces should be the same tr = wf.to_trace() tr = wfdisc2trace(wf) # get the raw data data = read_waveform(wf.dir + '/' + wf.dfile, wf.datatype, wf.foff, wf.nsamp) #do analysis, writing, and/or plotting here...
Adding waveforms to the database
Database-building scripts are in development, but adding waveforms to a database
is still relatively easy. Using ObsPy, any number of
can be read and the basic header "scraped" into a
Here's an example for a SAC file.
import os from glob import glob from obspy import read from pisces import db_connect from pisces.tables.css3 import Wfdisc session = db_connect(conn='sqlite:///mydatabase.sqlite') Wfdisc.__table__.create(session.bind) FTYPE = 'SAC' for ifile in glob("*.SAC"): tr = read(ifile, format='SAC') idir, idfile = os.path.split(ifile) wf = Wfdisc(sta=tr.stats.station, chan=tr.stats.channel, samprate=tr.stats.sampling_rate, nsamp=tr.stats.npts, time=tr.stats.starttime.timestamp, foff=634, dir=idir, dfile=idfile, endtime=tr.stats.endtime.timestamp) session.add(wf) session.commit() session.close()
Copying (localizing) waveform files
If you want to move waveform files from one database to another one, you may need copy the files
and tweak the Wfdisc table. Wfdisc tables contain
file name and directory information about the waveforms stored on disk, so those need to be
corrected when you move the files. In the example below, we copy wfdisc instances from
pointing to the originating database, to
session2, which points at the destination database.
import os import shutil def copy_waves(wfdiscs, old_base, new_base): """Replace old_base with new_base in the .dir attribute of wfdisc list, and copies the waveform files to the new location. Parameters ---------- wfdiscs : list Wfdisc instances from source database. old_base, new_base : str The top of the old (new) data directory trees. This assumes all wfdiscs originate and end up under single directories. The directory structure under the new_base will mirror that under old_base. Returns ------- wfdiscs_out : list Same as input list, but .dir attribute now points to the new_base location. """ for wf in wfdiscs: # replace the directory old_file = os.path.sep.join([wf.dir, wf.dfile]) wf.dir.replace(old_base, new_base) new_file = os.path.sep.join([wf.dir, wf.dfile]) try: shutil.copyfile(old_file, new_file) except IOError: # new directory doesn't exist yet. this is like "mkdir -p" os.makedirs(os.path.dirname(new_file)) shutil.copyfile(old_file, new_file) # get the wfdiscs wfs = session1.query(Wfdisc1).all() # release the link between the wfdiscs and the originating database # this makes them "floating" instances, so they can be added to the destination database session1.expunge_all(wfs) # do the copy and tweaking wfs = copy_waves(wfs, '/old/path/to/top/of/data', '/my/new/path/to/top/of/data') # add and commit them to the destination database session2.add_all(wfdiscs) session2.commit()