the waveform class - geoscience-community-codes/GISMO GitHub Wiki
Waveforms are the workhorse of the waveform suite. They contain information about the station, the data, the units, historical information, and any number of user-defined fields. Waveform takes care of the record keeping associated with the manipulation of its data.
Modifications to waveform objects are recorded in the history of each waveform. The history is capable of recording text blurbs as well as other types of information, such as other objects used to modify the waveform (e.g., details of an applied filter). Detailed history may later be retrieved to determine how the data were modified or, more importantly, how to reproduce results.
User-defined fields expand the capabilities of waveform by allowing users to include additional information relevant to each trace. In practice these user-defined fields serve as extensible header fields. These fields are created automatically in some instances; when a SAC file is imported, header information is transferred into user-defined fields. Though this information can be stored in adjacent matrices, incorporating it directly into the waveform object allows it to pass automatically into existing routines. Because these fields can be of any type it is possible to store not only simple information, (e.g., an event location), but also more complex information such as an instrument response or the frequency spectrum of the trace. While there is some danger in infinitely extensible header information, in our experience thus far this capability has given considerably more power than anticipated to the waveform suite. Access to the data within user-defined fields is through the same get and set methods that are used to access the rest of waveform's details.
The waveform class is designed to allow easy data retrieval from a variety of sources and to make basic waveform research quick and easy. It is a toolset that allows the creation of more sophisticated programs without having to be concerned with all details. Features include:
-
Use any regularly sampled data stream
-
Mathematical functions: +, -, /, .*, .^
-
Standard manipulations: filter, crop, subset, subset, stack, normalize, automatic gain control, demean, detrend, taper, etc.
-
Statistics: max, min, mean, median, etc.
-
Waveform operations: hilbert transform, integration and differentiation
-
Operate on single waveforms or thousands
-
History feature tracks changes to your waveforms
-
Plotting tools for all included data types
-
Object architecture provides a stable base for writing more complex programs
Data can be imported from Antelope databases (requires the BRTT Antelope toolbox), Winston databases, SAC and Seisan files. With minimal coding, most any homegrown MATLAB format can take advantage of the waveform architecture.
The waveform class:
-
makes playing with data easier by automating the tedious aspects of data manipulation
-
makes programs more stable by ensuring proper data typing
-
makes code more portable by reading multiple formats and functioning on multiple systems
-
makes troubleshooting faster by providing more detailed messages and warnings
Browse an extensive waveform tutorial and a primer on object-oriented programming in MATLAB.
Within these pages you'll find information to get you up and running with the Waveform Suite. The Waveform Suite is a collection of MATLAB classes that work together to speed up and simplify the import and manipulation of time-series data. Originally conceived to manipulate seismic data, it may be applied to any regularly sampled time-series data that is associated with a location.
Creating a Waveform
Generic information about the waveform constructor class
w = waveform
creates a blank waveform. You get a waveform with a blank station and channel, and a location and network of '--'
, a frequency of NaN
Hz, and a start time equal to antelope's default start time '1/1/1970 00:00:00'
. Changing any or all of this waveform's information can be done through the set function.
w = waveform(station, component, freq, start, data)
manually puts together a waveform object using each of these specified values. This is designed to allow you to create a waveform based on data from other places or from data that you've conjured up yourself. Additional values can be added/changed through the set function.
w =waveform(datasource, scnlobject, startTime,endTime)
Retrieves waveform(s) from the selected datasource, returning all waveforms that are described by the scnlobject list (ie, matching the correct station/channel/network/location parameters), for the times requested. The datasource object allows waveform to retrieve from any one of a number of sources: Antelope or Winston databases, SAC or SEISAN files, or even waveforms saved as .mat files.
What, exactly, is in a waveform object?
The beauty of object-oriented programing is that it really doesn't matter to the user how the information is stored, so long as it is accessible in a standard way
A waveform object contains only the following information:
- Scnlobject (station, channel, network, and location)
- Frequency
- Start time
- Data samples
- History
- User-defined Fields
You can use the struct(waveform) command to return the absolutely raw data and see for yourself... struct returns a structure based on the listed object.
However, much more information can be asked of it via the waveform/get routine.
Accessing
To retrieve information from waveforms, use the get method.
value = get(SCNLobject, 'PropertyToGet')
Here is a sample of the types of data / derived data that can be retrieved;
get(w,'station')
- returns the station call-sign. ie. VNSS, OKCF, etc...get(w,'freq')
- returns the frequency of the sample. this is an average sample rateget(w,'start_str')
- provides a readable date associated with this waveform's start timeget(w,'start_antelope')
- returns the start time in Antelope time. That is, the number of seconds elapsed since 1/1/1970get(w,'data')
- returns the vector of seismic data, same as double(data)get(w,'nyq')
- returns the nyquist frequency of the sampleget(w,'data_length')
- gives you the number of samples in your data setget(w,'duration')
- gives you the time-span of your data set
for additional valid properties, type help waveform/get
For a single waveform, the get method will return the requested property . For multiple waveforms, get will return either a numeric or cell array with the requested information.
Making direct changes to your waveform
Using set, you can change the values of your waveform. The general form of set is:
modifiedWave = set(originalWave, 'PropertyToChange', newValue)
If originalWave contains an array of waveforms, then that property is changed for all waveforms. Remember, the originalWave is unchanged until it is assigned the result.
Additional functions of note
Here are additional functions to be aware of:
Plot
plot one or more waveforms, labeling the graph as well as taking account of units
-
h = plot(waveform)
Plots a waveform object, handling the title and axis labeling. The output parameter h is optional. If used, the handle to the waveform plots will be returned. These can be used to change properties of the plotted waveforms. -
h = plot(waveform, ...)
Plots a waveform object, passing additional parameters to matlab's PLOT routine. -
h = plot(waveform, 'xunit', xvalue, ...)
sets the xunit property of the graph, which is used to determine how the times of the waveform are interpereted. Possible values for XVALUE are 'seconds', 'minutes', 'hours', 'days', 'day_of_year', 'date'. For multiple waveforms, specifying XUNITs of 'seconds', 'minutes', 'hours' will cause all the waveforms to be plotted starting at 0. An XUNIT of 'date' will force all waveforms to plot starting at their starttimes. the default XUNIT is seconds
For the following examples assume:
W is a 10-minute long waveform starting:04/02/2005 01:00:00
W2 is a 1-minute long waveform (same station) starting: 04/02/2005 01:05:00
PLOT EXAMPLE 1:
% This example plots the waveforms at their absolute times...
plot(W,'xunit','date'); % plots the waveform in blue
hold on;
h = plot(W2,'xunit','date', 'r', 'linewidth', 1);
% plots your other waveform in red, and with a wider line
PLOT EXAMPLE 2:
% This example plots the waveforms, starting at time 0
plot(W); % plots the waveform in blue with seconds on the x axis
hold on;
plot(W2,'xunit','seconds', 'color', [.5 .5 .5]); % plots your other
% waveform, starting in unison
% with the prev waveform, then
% change the color of the new
% plot to grey (RGB)
For a list of properties you can set (such as color, linestyle, etc...) type get(h) after plotting something.
Also, now Y can be autoscaled with the property pair: 'autoscale',true although it only works for single waveforms...
if the wave parameter is a vector of waveform objects, then plot will plot them all on the same axis, and to scale. You can also pass formatting comands to the plot function.
h = plot(wave,'xunit','date', 'r.-', 'linewidth', 1);
This plots your other waveform in a red dash-dotted line, and makes the line thicker.
demean
remove the voltage offset from the data. This basically just subtracts the mean of the data. One nice feature is that this is designed to work with arrays of waveform objects.
fixedWave = demean(VNSS20050403PMwave);
mean
figures out the average (mean) of the waveform's data, then returns that value as a scalar.
avgVoltageOffset = mean(mySampleWave);
You can also pass this function an array of waveforms, and it will return a same-shaped array of mean values.
hilbert
returns the real part of a hilbert transform based on the waveform's data.
This is great for generating envelopes.
hilbert_envelope = hilbert(mySampleWave);
stack
combines waveforms. If you have waveform objects with similar sample rates and durations, you can stack their waveforms.
This clones the first waveform in the array, (station ID, start time, etc) and then sums the data from each of the included waveforms. This does no error checking, so it will crash if your arrays don't overlap. You'll definitely want to change the header information for the waveform using the get command after successfully stacking things, so that it becomes obvious that the data is stacked.
% In this example, veni1 .. veni4 are waveform objects
w = [veni1 veni2 veni3 veni4];
mystack = stack(w);
mystack = set(mystack,'STATION','VNSS_Stack');
extract
returns a waveform consisting of a subset of data from within another waveform array.
Let's start with a waveform that was loaded like so:
bigWave = waveform('OKCF','SHZ','10/5/2005 12:00','10/5/2005 24:00');
Twelve hours of data... that's an awful big wave to have to deal with, especially at a 100Hz sample rate. Maybe I'd like to work with the 14:00 - 15:00 subsection... You could go back to the database and reload. But, maybe you've done some funky filtering or something else that you don't want to have to repeat. Here are two ways to do that:
subWave = extract(bigWave,'TIME','10/5/2005/14:00','10/5/2005 15:00');
subWave = extract (bigWave,'Index&Duration', 100 * 60 * 60 * 2, '1:00');
Where 100 * 60 * 60 * 2 is the expected offset of your second hour of data...
fix_data_length
sets the data from multiple waveforms to the same length, Several functions in matlab require using data of the same length, and this function will do that. By default, it will find the longest waveform, and then pad all the others with zero to make them match up.
myWaves = fix_data_length(myWaves);
Examples
Several examples can be checked out from
example index (several) another example (w/ antelope)
External Example links
These links are to an old Waveform Suite website, hosted at the University of Alaska Geophysical Institute, Seismology Lab.
- [multiple examples] (http://kiska.giseis.alaska.edu/input/celso/matlabweb/waveform_suite/waveform_suite_example_index.html)
- Example using antelope
Note, the download links are to an OLD version of the waveform suite.
Information on this page was ported from: http://kiska.giseis.alaska.edu/input/celso/matlabweb/waveform_suite/waveform.html