Function index
Public types and functions
Types
Seis.Trace — TypeTraceEvenly-sampled time series recorded at a single seismic station. The start time of the trace, in s, is in the b property, whilst the sampling interval, in s, is delta. The trace itself is accessed using the trace method, like trace(t).
All Traces are relative to the event time evt.time if it is defined, regardless of what the event is. For example, evt.time could be the origin time of an earthquake, or a picked arrival time.
The trace then contains information about an associated Event in evt and the Station in sta. picks holds a dictionary which contains pairs of pick times relative to the origin and names (which can be missing). Access picks with the picks method, and add picks with add_pick!.
The meta Dict holds any other information about the trace.
If the event time is set, then the trace beginning time b is relative to this.
Find the trace start time relative to the origin time using starttime. The absolute start time and date, if an origin time is set, is given by startdate.
Seis.AbstractTrace — TypeAbstractTraceAbstract type from which you should subtype if creating new types of traces.
Interface
The formal interface for AbstractTraces is still a work in progress and may change with a minor version increment.
The following methods should be defined for all AbstractTraces:
trace(t): Return the data for the trace.times(t): Return the time at each sample oft.starttime(t): The time of the first sample.nsamples(t): The number of samples int.Base.eltype(t): The element type of the data samples.
Seis.CartTrace — TypeCartTraceAlias for Trace where Event and Station coordinates are Seis.Cartesian rather than Seis.Geographic
Seis.Event — TypeEventType containing information about a seismic event. Fields lon and lat are epicentral location in °; dep is depth below the reference (e.g., sea level) in km. time is a Dates.DateTime giving the event origin date and time, while id is a string holding the event identifier. meta is a Dict holding any extra information about the event.
Missing information is allowed and stored as missing.
Seis.CartEvent — TypeCartEvent{T}Alias for Event{T, Cartesian{T}} where T, representing an Event with Cartesian coordinates.
This type is useful for dispatch, allowing one to write methods which are only applicable when a Event has Cartesian coordinates.
Example
julia> using Geodesy
julia> Geodesy.LLA(evt::CartEvent) = LLA(evt.x, evt.y, evt.z)Seis.Station — TypeStationStruct containing information about a seismic station. Fields net, sta, loc and cha are the station, network, channel and location codes respectively, whilst lon and lat are the location in °. Set station depth dep and elevation elev in m relative to the reference level. The azimuth azi and inclination inc of the channel in ° are respectively measured from north to east, and downward from the vertical. (E.g., a "BHN" channel typically will have a azi == 0 and inc == 90.)
meta is a Dict holding any extra information about the station or channel.
Missing information is allowed and stored as missing.
Seis.CartStation — TypeCartStation{T} where TAlias for Station{T, Cartesian{T}} where T, representing a Station with Cartesian coordinates.
This type is useful for dispatch, allowing one to write methods which are only applicable when a Station has Cartesian coordinates.
Example
Create a function which obtains the east-north-up coordinates of a Station
julia> using Geodesy
julia> Geodesy.ENU(sta::CartStation) = ENU(sta.x, sta.y, sta.z)
julia> ENU(CartStation(x=1, y=2, z=3))Accessor functions
Seis.channel_code — Functionchannel_code(t::Trace) -> code
channel_code(s::Station) -> codeReturn the channel code for trace t or station s, in the form of "⟨network⟩.⟨name⟩.⟨location⟩.⟨component⟩". Missing fields are left blank. The information is taken respectively from the net, sta, cha and loc fields of the Station.
Seis.dates — Functiondates(t) -> date_rangeReturn a date_range which contains the dates for each sample of t, so long as t.evt.time is defined. If not, an error is thrown.
N.B. This function assumes that the sampling interval t.delta is representable as an integer number of milliseconds, and rounds it accordingly. Dates.DateTimes have precision of 1 ms. An error is thrown if t.delta < 1e-3 s.
Example
julia> t = sample_data();
julia> dates(t)
1981-03-29T10:39:06.66:10 milliseconds:1981-03-29T10:39:16.65See also: times.
Seis.enddate — Functionenddate(t) -> dateReturn the date of the last sample of the trace t.
N.B. This function assumes that the sampling interval t.delta is representable as an integer number of milliseconds, and rounds it accordingly. Dates.DateTimes have precision of 1 ms. An error is thrown if t.delta < 1e-3 s.
Example
julia> t = sample_data(); t.evt.time
1981-03-29T10:38:14
julia> enddate(t)
1981-03-29T10:39:16.65Seis.endtime — Functionendtime(t) -> timeReturn the end time of trace t in seconds.
Example
julia> t = Trace(5, 1, 3); # 3 samples at 1 Hz, starting at 5 s
julia> endtime(t)
7.0Seis.is_east — Functionis_east(s::Station; tol) -> ::Bool
is_east(t::AbstractTrace; tol) -> ::BoolReturn true if the trace t or station s is horizontal and points to the east.
The azimuth and inclination of the trace is compared to east and the horizontal within a tolerance of tol°. The default is set to be appropriate for the floating-point type used for the station or trace, but can be overridden by passing a comparison to tol.
See also: is_north, is_vertical
Seis.is_north — Functionis_north(s::Station{T}; tol) where T -> ::Bool
is_north(t::AbstractTrace; tol) -> ::BoolReturn true if the trace t is horizontal and points to the north.
The azimuth and inclination of the trace is compared to east and the horizontal within a tolerance of tol°. The default is set to be appropriate for the floating-point type used for the station or trace, but can be overridden by passing a comparison to tol.
See also: is_east, is_vertical
Seis.is_horizontal — Functionis_horizontal(s::Station; tol)
is_horizontal(t::AbstractTrace; tol) -> ::BoolReturn true if the trace t is horizontal (i.e., its inclination is 90° from the vertical), and false otherwise.
The inclination of the trace is compared to the horizontal within a tolerance of tol°. The default is set to be appropriate for the floating-point type used for the station or trace, but can be overridden by passing a comparison to tol.
Examples
julia> s = Station(azi=0, inc=90);
julia> is_horizontal(s)
true
julia> t = sample_data();
julia> is_horizontal(t)
false
julia> t.sta.inc
0.0f0See also: is_vertical, is_east, is_north.
Seis.is_vertical — Functionis_vertical(s::Station{T}; tol=eps(T)) where T
is_vertical(t::AbstractTrace; tol=eps(eltype(trace(t)))) -> ::BoolReturn true if the trace t is vertical (i.e., its inclination is 0°), and false otherwise.
The inclination of the trace is compared to the vertical within a tolerance of tol°. The default is set to be appropriate for the floating-point type used for the station or trace, but can be overridden by passing a comparison to tol.
Examples
julia> s = Station(azi=0, inc=90);
julia> is_vertical(s)
false
julia> t = sample_data();
julia> is_vertical(t)
trueSee also: is_horizontal.
Seis.nearest_sample — Functionnearest_sample(t::AbstractTrace, time; inside=true) -> iReturn the index i of the nearest sample of the trace t to time seconds.
If inside is true (the default), return nothing when time lies outside the trace. Set inside to false to instead return the first or last index when time is outside the trace.
Examples
julia> t = Trace(0, 1, rand(5)); # Trace starting at 0 s, 1 Hz sampling
julia> nearest_sample(t, 2)
3
julia> nearest_sample(t, -1)
julia> nearest_sample(t, -1, inside=false)
1nearest_sample(t::AbstractTrace, datetime::DateTime; inside=true)Form of nearest_sample where datetime is given as absolute time.
An error is thrown if no origin time is specified for t.evt.time.
Example
julia> using Dates: DateTime, Second
julia> t = sample_data();
julia> nearest_sample(t, DateTime(1981, 03, 29, 10, 39, 7))
35
julia> nearest_sample(t, startdate(t) - Second(10)) # 10 s before the first sample
julia> nearest_sample(t, startdate(t) - Second(10), inside=false)
1Seis.nsamples — Functionnsamples(t) -> nReturn the number of samples n in a trace t.
Example
julia> data = rand(4);
julia> t = Trace(0, 1, data);
julia> nsamples(t)
4nsamples(t, b, e) -> nReturn the number of samples n in a trace t between times b and e seconds.
This function only counts samples that are strictly on or later than the b time, and before or on the e time.
Example
julia> t = Trace(0, 1, 25); # 25 samples from 0s to 24 s
julia> nsamples(t, 3, 4.1)
2See also: nearest_sample.
nsamples(t, start::DateTime, stop::DateTime) -> nReturn the number of samples n in a trace t between dates start and stop.
Example
julia> using Dates
julia> t = Trace(10, 1, 20); # 20 samples from 10 to 30 s
julia> t.evt.time = DateTime(3000)
3000-01-01T00:00:00
julia> nsamples(t, DateTime(3000), DateTime(3000) + Second(9))
0
julia> nsamples(t, DateTime(3000) + Second(20), DateTime(3000) + Second(22))
3Seis.picks — Functionpicks(t; sort=nothing) -> p::Vector{Tuple{<:AbstractString,<:AbstractFloat}}Return a vector p of Seis.Picks, which contain pairs of pick times and names associated with the Trace t.
This can be iterated like:
julia> t = Trace(0, 1, rand(10));
julia> add_pick!.(t, (1,2), ("P","S"));
julia> for (time, name) in picks(t) @show time, name end
(time, name) = (1.0, "P")
(time, name) = (2.0, "S")picks(t, name::AbstractString; sort=:time) -> p
picks(t, pattern::Regex; sort=:time) -> pReturn a vector p of pairs of pick names and times associated with the Trace t which either are exactly name or match the regular expression pattern.
By default, picks are returned in order of increasing time. Use sort=:name to sort alphanumerically by name (where unnamed picks appear first).
Example
julia> t = Trace(0, 1, 2); t.picks.P = (1, "Pn"); t.picks.S = (1.8, "S");
julia> t.picks
Seis.SeisDict{Union{Int64, Symbol},Seis.Pick{Float64}} with 2 entries:
:P => Seis.Pick{Float64}(time=1.0, name="Pn")
:S => Seis.Pick{Float64}(time=1.8, name="S")
julia> picks(t, "S")
1-element Array{Seis.Pick{Float64},1}:
Seis.Pick{Float64}(time=1.8, name="S")
julia> picks(t, r"^P")
1-element Array{Seis.Pick{Float64},1}:
Seis.Pick{Float64}(time=1.0, name="Pn")Seis.startdate — Functionstartdate(t) -> dateReturn the date of the first sample of the trace t.
N.B. This function assumes that the sampling interval t.delta is representable as an integer number of milliseconds, and rounds it accordingly. Dates.DateTimes have precision of 1 ms. An error is thrown if t.delta < 1e-3 s.
Example
julia> t = sample_data(); t.evt.time
1981-03-29T10:38:14
julia> startdate(t)
1981-03-29T10:39:06.66Seis.starttime — Functionstarttime(t) -> timeReturn the start time of trace t in seconds.
Example
julia> t = Trace(-3, 0.01, rand(20)) # Set start time to -3;
julia> starttime(t)
-3.0Seis.times — Functiontimes(t) -> rangeReturn the set of times range at which each sample of the trace t is defined.
Example
julia> t = sample_data();
julia> times(t)
52.66f0:0.01f0:62.65f0See also: dates.
Seis.trace — Functiontrace(t) -> dataReturn an array data containing the values of the Trace t at each sampling point. data is now a variable bound to ts values, and changing data will change t. trace(t) may itself also be modified and the trace will be updated.
The value returned by trace is a variable bound to an internal field of the trace. Therefore, assigning another value to trace(t) or data will not update the values in t. Instead, update the values in-place using the . operator (like data .= 1). See examples below.
The underlying data array holding the trace can be rebound by assigning to the trace's field t, but this is unsupported and may break in future.
Examples
Retrieving the data values for a trace, and modifying the first value.
julia> t = sample_data();
julia> data = trace(t)
1000-element Array{Float32,1}:
-0.09728001
-0.09728001
⋮
-0.0768
-0.0768
julia> data[1] = 0;
julia> trace(t)
1000-element Array{Float32,1}:
0.0
-0.09728001
⋮
-0.0768
-0.0768Setting the data values for a new synthetic trace.
julia> t = Trace(0, 0.01, 1000); # 1000-point, 100 Hz trace with random data
julia> trace(t) .= sin.(π.*times(t));
julia> trace(t)
1000-element Array{Float64,1}:
0.0
0.03141075907812829
⋮
-0.06279051952931425
-0.031410759078131116Setter functions
Seis.add_pick! — Functionadd_pick!(t, time [, name=missing]) -> (time, name)Add an arrival time pick to the Trace t, ensuring existing picks are not overwritten.
If name is not missing, then the key of this pick will be Symbol(name), unless another pick with the same key already exists. In that case, the name will be appended with a number which increases until an available key is found.
If name is missing, then the pick is added to a numbered set of picks.
(Direct manipulation of picks is easy: just do t.picks.PKP = (1001, "PKP") to set a picks with name "PKP", time 1001 s and key :PKP.)
Example
julia> t = Trace(0, 1, 2);
julia> add_pick!.(t, [1, 2], ["A", missing]);
julia> t.picks
Seis.SeisDict{Union{Int64, Symbol},Seis.Pick{Float64}} with 2 entries:
:A => Seis.Pick{Float64}(time=1.0, name="A")
1 => Seis.Pick{Float64}(time=2.0, name=missing)
julia> add_pick!(t, 4)
Seis.Pick{Float64}(time=4.0, name=missing)
julia> t.picks
Seis.SeisDict{Union{Int64, Symbol},Seis.Pick{Float64}} with 3 entries:
:A => Seis.Pick{Float64}(time=1.0, name="A")
2 => Seis.Pick{Float64}(time=4.0, name=missing)
1 => Seis.Pick{Float64}(time=2.0, name=missing)
julia> t.picks.A
Seis.Pick{Float64}(time=1.0, name="A")
julia> t.picks[1]
Seis.Pick{Float64}(time=2.0, name=missing)See also: Seis.Pick.
add_pick!(t, p::Pick, name=p.name) -> pAdd a travel time pick to the Trace t from a Seis.Pick. By default, the pick name is used.
Example
julia> t1 = Trace(0, 1, 20); t2 = sample_data();
julia> add_pick!(t1, t2.picks.A, "A")
Seis.Pick{Float64}(time=53.67000198364258, name="A")
julia> t1.picks
Seis.SeisDict{Union{Int64, Symbol},Seis.Pick{Float64}} with 1 entry:
:A => Seis.Pick{Float64}(time=53.67000198364258, name="A")Seis.add_picks! — Functionadd_picks!Add picks to traces based on seismic phases' predicted arrival time.
Seis does not itself implement seismic phase travel time computation. See SeisTau for one implementation which adds methods to add_pick!.
Seis.clear_picks! — Functionclear_picks!(t)Remove all picks associated with the Trace t.
Example
julia> t = sample_data();
julia> picks(t)
2-element Array{Seis.Pick{Float32},1}:
Seis.Pick{Float32}(time=53.670002, name=missing)
Seis.Pick{Float32}(time=60.980003, name=missing)
julia> clear_picks!(t);
julia> picks(t)
0-element Array{Seis.Pick{Float32},1}Seis.origin_time! — Functionorigin_time!(t, time::DateTime; picks=true) -> tSet the origin time of the trace t and shift the start time of the trace (stored in its .b field) so that the absolute time of all samples remains the same.
origin_time! will also shift all pick times so that they remain at the same absolute time. Set picks=false to leave picks at the same time relative to the trace start time.
If t.evt.time is missing (i.e., unset), then it is simply set to time and no times are shifted.
Example
julia> using Dates
julia> t = sample_data(); t.picks
Seis.SeisDict{Union{Int64, Symbol},Seis.Pick{Float32}} with 2 entries:
:F => Seis.Pick{Float32}(time=60.980003, name=missing)
:A => Seis.Pick{Float32}(time=53.670002, name=missing)
julia> t.evt.time
1981-03-29T10:38:14
julia> origin_time!(t, t.evt.time + Second(1)); t.evt.time
1981-03-29T10:38:15
julia> t.picks
Seis.SeisDict{Union{Int64, Symbol},Seis.Pick{Float32}} with 2 entries:
:F => Seis.Pick{Float32}(time=59.980003, name=missing)
:A => Seis.Pick{Float32}(time=52.670002, name=missing)Seis.origin_time — Functionorigin_time(t, time::DateTime; picks=true) -> t′Return a copy to t where the event origin time is shifted to time.
See the in-place version origin_time! for more details.
Geometry functions
Seis.azimuth — Functionazimuth(trace; sphere=false, flattening=Geodesics.F_WGS84) -> az
azimuth(event, station; sphere=false, flattening=Geodesics.F_WGS84) -> azReturn the azimuth az from the event to the station (a seismic station) in degrees east from local north at the event for a trace. Alternatively specify the event and station individually.
Optionally specify the flattening of the ellipsoid of rotation on which this is computed, which defaults to that of the WGS84 ellipsoid. If sphere is true, then flattening is set to zero and the calculation is performed on a sphere.
Seis.backazimuth — Functionbackazimuth(trace; flattening=0.0033528106718309896) -> baz
backazimuth(station, event; flattening=0.0033528106718309896) -> bazReturn the backazimuth baz from the station (a seismic station) to an event in degrees east from local north at the station for a trace. Alternatively specify the station and event individually.
Optionally specify the flattening of the ellipsoid of rotation on which this is computed, which defaults to that of the WGS84 ellipsoid. If sphere is true, then flattening is set to zero and the calculation is performed on a sphere.
Seis.distance_deg — Functiondistance_deg(trace; sphere=false, flattening=0.0033528106718309896) -> Δ
distance_deg(station, event; sphere=false, flattening=0.0033528106718309896) -> Δ
distance_deg(event, station; sphere=false, flattening=0.0033528106718309896) -> ΔFor a trace or an event-station pair, return the epicentral angular distance Δ in degrees.
Optionally specify the flattening of the ellipsoid of rotation on which this is computed, which defaults to that of the WGS84 ellipsoid. If sphere is true, then flattening is set to zero and the calculation is performed on a sphere.
Seis.distance_km — Functiondistance_km(event, station; sphere=false, a=6378.137, flattening=0.0033528106718309896) -> dFor a geographic trace or event–station pair, return the epicentral surface distance d in km between them.
Optionally specify the semimajor radius a in km and flattening of the ellipsoid of rotation on which this is computed, which defaults to that of the WGS84 ellipsoid. If sphere is true, then flattening is set to zero and the calculation is performed on a sphere.
distance_km(event, station) -> dFor a cartesian trace or event-station pair, return the epicentral distance in km between them.
Seis.incidence — Functionincidence(event, station) -> i
incidence(trace) -> iReturn the angle of incidence i° between a cartesian event and station, or a cartesian trace. The angle of incidence is defined downwards from the positive z (upward) direction.
Trace operations
Seis.cut! — Functioncut!(t, start, end; allowempty=false, warn=true) -> tCut a Trace t in place between start and end. An error is thrown if either start or end are missing.
An error is thrown if the trace would be empty because either the end cut time is before the start of the trace, or the start cut is after the end, unless allowempty is true.
By default, a warning is shown if cut times lie outside the trace; set warn to false to turn this off.
Example
julia> t = Trace(0, 1, [0, 1, 2, 3, 4, 5]);
julia> trace(cut!(t, 2, 4))
3-element Array{Float64,1}:
2.0
3.0
4.0cut!(t, start_date, end_date; kwargs...) -> tCut a Trace t in place between dates start_date and end_date.
cut!(t, pick1, offset1, pick2, offset; kwargs...) -> t
cut!(t, pick, offset1, offset2; kwargs...) ->Cut a trace t in place between offset1 s after the first pick pick1 and offset2 s after pick2.
In the second form, both offsets are relative to pick.
The values of pick1, pick2 and pick are passed to picks and so may be a Symbol (giving the key of the pick), a String (giving the pick name) or a Regex (which matches the pick name).
Example
julia> t = sample_data();
julia> starttime(t), endtime(t)
(52.66f0, 62.65f0)
julia> cut!(t, :A, 0, :F, 1);
julia> starttime(t), endtime(t)
(53.67f0, 61.979996f0)Seis.cut — Functioncut(t, start, end; kwargs...) -> t′
cut(t, start_date, end_date; kwargs...) -> t′
cut(t, pick1, offset1, pick2, offset2; kwargs...) -> t′
cut(t, pick, offset1, offset2; kwargs...) -> t′Return a copy of the trace t cut between start and end s relative to the event origin. You may also specify a start_date and end_date, or choose times offset1 and offset2 s relative to pick1 and pick2 respectively. Both offset times may also be specified relative to one pick.
Seis.decimate! — Functiondecimate!(t, n; antialias=true) -> t
decimate(t, n; antialias=true) -> t′Decimate the trace t by removing all except every n points. The sampling interval is increased n times. In the first form, update the trace in place and return it. In the second form, return an updated copy.
By default, an antialiasing and decimation FIR filter is applied. This may cause artifacts in the signal at the extremes of the trace.
If antialias is false, then no antialiasing filtering is applied during decimation. This means the decimated trace may contain spurious signals.
Seis.decimate — Functiondecimate!(t, n; antialias=true) -> t
decimate(t, n; antialias=true) -> t′Decimate the trace t by removing all except every n points. The sampling interval is increased n times. In the first form, update the trace in place and return it. In the second form, return an updated copy.
By default, an antialiasing and decimation FIR filter is applied. This may cause artifacts in the signal at the extremes of the trace.
If antialias is false, then no antialiasing filtering is applied during decimation. This means the decimated trace may contain spurious signals.
Seis.differentiate! — Functiondifferentiate!(t::Trace; points=2) -> t
differentiate(t::Trace; points=2) -> t′Differentiate the trace t by performing points-point finite differencing. In the first form, update the trace in place and return it. In the second form, return an updated copy.
Available algorithms
points == 2: Two-point.dsdt.t[i] = (t.t[i+1] - t.t[i])/t.delta. Non-central difference, sot.bis increased by halft.delta. The trace length is reduced by 1 samples.points == 3: Three-point.dsdt.t[i] = (t.t[i+1] - t.t[i-1])/(2 * t.delta). Central difference.t.bis increased byt.delta; the trace length is reduced by 2 samples.points == 5: Five-point.dsdt.t[i] = (2/3)*(t.t[i+1] - t.t[i-1])/t.delta - (1/12)*(t.t[i+2] - t.t[i-2])/t.delta. Central difference.t.bis increased by2t.delta;nptsreduced by 4.
Example
julia> t = Trace(0, 1, [0, 1, -1, 0]);
julia> d = differentiate(t); trace(d)
3-element Array{Float64,1}:
1.0
-2.0
1.0
julia> starttime(d)
0.5Seis.differentiate — Functiondifferentiate!(t::Trace; points=2) -> t
differentiate(t::Trace; points=2) -> t′Differentiate the trace t by performing points-point finite differencing. In the first form, update the trace in place and return it. In the second form, return an updated copy.
Available algorithms
points == 2: Two-point.dsdt.t[i] = (t.t[i+1] - t.t[i])/t.delta. Non-central difference, sot.bis increased by halft.delta. The trace length is reduced by 1 samples.points == 3: Three-point.dsdt.t[i] = (t.t[i+1] - t.t[i-1])/(2 * t.delta). Central difference.t.bis increased byt.delta; the trace length is reduced by 2 samples.points == 5: Five-point.dsdt.t[i] = (2/3)*(t.t[i+1] - t.t[i-1])/t.delta - (1/12)*(t.t[i+2] - t.t[i-2])/t.delta. Central difference.t.bis increased by2t.delta;nptsreduced by 4.
Example
julia> t = Trace(0, 1, [0, 1, -1, 0]);
julia> d = differentiate(t); trace(d)
3-element Array{Float64,1}:
1.0
-2.0
1.0
julia> starttime(d)
0.5Seis.envelope! — Functionenvelope!(t::Trace) -> t
envelope(t::Trace) -> t′Replace the trace t with its envelope. In the first form, update the trace in place and return the trace. In the second form, return an updated copy.
Example
julia> t = Trace(0, 1, [0, 0, 0, 1, -1, 0, 0, 0]);
julia> trace(envelope(t))
8-element Array{Float64,1}:
0.10355339059327379
0.10355339059327379
0.6035533905932737
1.1680225577002512
1.1680225577002512
0.6035533905932737
0.10355339059327373
0.10355339059327379Seis.envelope — Functionenvelope!(t::Trace) -> t
envelope(t::Trace) -> t′Replace the trace t with its envelope. In the first form, update the trace in place and return the trace. In the second form, return an updated copy.
Example
julia> t = Trace(0, 1, [0, 0, 0, 1, -1, 0, 0, 0]);
julia> trace(envelope(t))
8-element Array{Float64,1}:
0.10355339059327379
0.10355339059327379
0.6035533905932737
1.1680225577002512
1.1680225577002512
0.6035533905932737
0.10355339059327373
0.10355339059327379Seis.flip! — Functionflip!(t) -> t
flip(t) -> t′Reverse the direction of a trace so that it points the opposite way. This preserves the sense of the data; for example, a positive signal on an eastward-pointing channel becomes a negative signal on the flipped westward pointing channel. Both before and after, the signal is positive eastwards.
The t.sta must contain both azimuth and inclination information.
In the first form, update the trace in place and return the trace. In the second form, return an updated copy.
Example
julia> t = Trace(0, 1, [0, 1, 0]); # Positive arrival at 1 s
julia> t.sta.azi, t.sta.inc = 0, 90 # North horizontal component
(0, 90)
julia> flip!(t)
Seis.Trace{Float64,Array{Float64,1},Seis.Geographic{Float64}}:
b: 0.0
delta: 1.0
Station{Float64,Seis.Geographic{Float64}}:
sta.cha: 180.0
sta.azi: 180.0
sta.inc: 90.0
sta.meta: Seis.SeisDict{Symbol,Any}()
Event{Float64,Seis.Geographic{Float64}}:
evt.meta: Seis.SeisDict{Symbol,Any}()
Trace:
picks: 0
meta:
julia> trace(t)
3-element Array{Float64,1}:
-0.0
-1.0
-0.0Seis.flip — Functionflip!(t) -> t
flip(t) -> t′Reverse the direction of a trace so that it points the opposite way. This preserves the sense of the data; for example, a positive signal on an eastward-pointing channel becomes a negative signal on the flipped westward pointing channel. Both before and after, the signal is positive eastwards.
The t.sta must contain both azimuth and inclination information.
In the first form, update the trace in place and return the trace. In the second form, return an updated copy.
Example
julia> t = Trace(0, 1, [0, 1, 0]); # Positive arrival at 1 s
julia> t.sta.azi, t.sta.inc = 0, 90 # North horizontal component
(0, 90)
julia> flip!(t)
Seis.Trace{Float64,Array{Float64,1},Seis.Geographic{Float64}}:
b: 0.0
delta: 1.0
Station{Float64,Seis.Geographic{Float64}}:
sta.cha: 180.0
sta.azi: 180.0
sta.inc: 90.0
sta.meta: Seis.SeisDict{Symbol,Any}()
Event{Float64,Seis.Geographic{Float64}}:
evt.meta: Seis.SeisDict{Symbol,Any}()
Trace:
picks: 0
meta:
julia> trace(t)
3-element Array{Float64,1}:
-0.0
-1.0
-0.0Seis.integrate! — Functionintegrate!(t::Trace, method=:trapezium) -> t
integrate(t::Trace, method=:trapezium) -> t′Replace t with its time-integral. This is done by default using the trapezium rule. Use method=:rectangle to use the rectangle rule.
In the first form, update the trace in place and return the trace. In the second form, return an updated copy.
If method==:trapezium (the default), then the number of samples is reduced by one and the begin time is increased by half the sampling interval.
Example
julia> t = Trace(0, 0.1, [0, 1, 1, 0]);
julia> trace(integrate(t))
3-element Array{Float64,1}:
0.05
0.15000000000000002
0.2
julia> trace(integrate(t, :rectangle))
4-element Array{Float64,1}:
0.0
0.1
0.2
0.2Seis.integrate — Functionintegrate!(t::Trace, method=:trapezium) -> t
integrate(t::Trace, method=:trapezium) -> t′Replace t with its time-integral. This is done by default using the trapezium rule. Use method=:rectangle to use the rectangle rule.
In the first form, update the trace in place and return the trace. In the second form, return an updated copy.
If method==:trapezium (the default), then the number of samples is reduced by one and the begin time is increased by half the sampling interval.
Example
julia> t = Trace(0, 0.1, [0, 1, 1, 0]);
julia> trace(integrate(t))
3-element Array{Float64,1}:
0.05
0.15000000000000002
0.2
julia> trace(integrate(t, :rectangle))
4-element Array{Float64,1}:
0.0
0.1
0.2
0.2Seis.normalise! — Functionnormalise!(t::Trace, val=1) -> t
normalise(t::Trace, val=1) -> t′Normalise the trace t so that its maximum absolute amplitude is val. In the first form, update the trace in place and return the trace. In the second form, return an updated copy.
This function can also be spelled normalize[!].
Example
julia> t = Trace(0, 0.1, [0, -1, 2]);
julia> trace(normalise(t))
3-element Array{Float64,1}:
0.0
-0.5
1.0
julia> trace(normalise(t, 2))
3-element Array{Float64,1}:
0.0
-1.0
2.0Seis.normalise — Functionnormalise!(t::Trace, val=1) -> t
normalise(t::Trace, val=1) -> t′Normalise the trace t so that its maximum absolute amplitude is val. In the first form, update the trace in place and return the trace. In the second form, return an updated copy.
This function can also be spelled normalize[!].
Example
julia> t = Trace(0, 0.1, [0, -1, 2]);
julia> trace(normalise(t))
3-element Array{Float64,1}:
0.0
-0.5
1.0
julia> trace(normalise(t, 2))
3-element Array{Float64,1}:
0.0
-1.0
2.0LinearAlgebra.normalize! — Functionnormalise!(t::Trace, val=1) -> t
normalise(t::Trace, val=1) -> t′Normalise the trace t so that its maximum absolute amplitude is val. In the first form, update the trace in place and return the trace. In the second form, return an updated copy.
This function can also be spelled normalize[!].
Example
julia> t = Trace(0, 0.1, [0, -1, 2]);
julia> trace(normalise(t))
3-element Array{Float64,1}:
0.0
-0.5
1.0
julia> trace(normalise(t, 2))
3-element Array{Float64,1}:
0.0
-1.0
2.0LinearAlgebra.normalize — Functionnormalise!(t::Trace, val=1) -> t
normalise(t::Trace, val=1) -> t′Normalise the trace t so that its maximum absolute amplitude is val. In the first form, update the trace in place and return the trace. In the second form, return an updated copy.
This function can also be spelled normalize[!].
Example
julia> t = Trace(0, 0.1, [0, -1, 2]);
julia> trace(normalise(t))
3-element Array{Float64,1}:
0.0
-0.5
1.0
julia> trace(normalise(t, 2))
3-element Array{Float64,1}:
0.0
-1.0
2.0Seis.remove_mean! — Functionremove_mean!(t::Trace) -> t
remove_mean(t::Trace) -> t′Remove the mean of trace t. In the first form, update the trace in place and return it. In the second form, return an updated copy.
Example
julia> t = Trace(0, 0.01, [1, 1, 3, -1]);
julia> trace(remove_mean(t))
4-element Array{Float64,1}:
0.0
0.0
2.0
-2.0Seis.remove_mean — Functionremove_mean!(t::Trace) -> t
remove_mean(t::Trace) -> t′Remove the mean of trace t. In the first form, update the trace in place and return it. In the second form, return an updated copy.
Example
julia> t = Trace(0, 0.01, [1, 1, 3, -1]);
julia> trace(remove_mean(t))
4-element Array{Float64,1}:
0.0
0.0
2.0
-2.0Seis.remove_trend! — Functionremove_trend!(t::Trace) -> t
remove_trend(t::Trace) -> t′Remove the trend from t. In the first form, update the trace in place and return it. In the second form, return an updated copy.
Example
julia> t = Trace(0, 0.2, [1, 2, 3, 4]);
julia> trace(remove_trend(t))
4-element Array{Float64,1}:
-2.220446049250313e-16
0.0
0.0
4.440892098500626e-16Seis.remove_trend — Functionremove_trend!(t::Trace) -> t
remove_trend(t::Trace) -> t′Remove the trend from t. In the first form, update the trace in place and return it. In the second form, return an updated copy.
Example
julia> t = Trace(0, 0.2, [1, 2, 3, 4]);
julia> trace(remove_trend(t))
4-element Array{Float64,1}:
-2.220446049250313e-16
0.0
0.0
4.440892098500626e-16Seis.taper! — Functiontaper!(t::AbstractTrace, width=0.05, form=:hanning) -> t
taper(t::AbstractTrace, width=0.05, form=:hamming) -> t′Apply a symmetric taper to each end of the data in trace t. form may be one of :hanning, :hamming or :cosine. width represents the fraction (at both ends) of the trace tapered, up to 0.5.
In the first form, update the trace in place and return it. In the second form, return an updated copy.
Example
julia> t = Trace(0, 1, [-1, 1, -1, 1, -1, 1]);
julia> trace(taper(t))
6-element Array{Float64,1}:
-0.0
0.49999999999999994
-1.0
1.0
-0.49999999999999994
0.0Seis.taper — Functiontaper!(t::AbstractTrace, width=0.05, form=:hanning) -> t
taper(t::AbstractTrace, width=0.05, form=:hamming) -> t′Apply a symmetric taper to each end of the data in trace t. form may be one of :hanning, :hamming or :cosine. width represents the fraction (at both ends) of the trace tapered, up to 0.5.
In the first form, update the trace in place and return it. In the second form, return an updated copy.
Example
julia> t = Trace(0, 1, [-1, 1, -1, 1, -1, 1]);
julia> trace(taper(t))
6-element Array{Float64,1}:
-0.0
0.49999999999999994
-1.0
1.0
-0.49999999999999994
0.0Filtering
Seis.bandstop! — Functionbandstop!(t::Trace, f1, f2; poles=2, twopass=false, kind=DSP.Butterworth(poles)) -> t
bandstop(t::Trace, f1, f2; poles=2, twopass=false, kind=DSP.Butterworth(poles)) -> t′Apply a bandreject filter to the trace t with stop band between frequencies f1 and f2 in Hz. In the first form, update the trace in place and return it. In the second form, return an updated copy.
Optionally specify the number of poles of the filter, and whether a two-pass filter should be applied. This doubles the effective number of poles, because both a forward and reverse pass occur. This has the advantage of preserving the phase.
Specify the kind of filter by providing a kind from the DSP.Filters module. If doing so, the poles keyword argument is not used and the number of poles, ripple power, etc., should be specified when providing the filter kind.
Seis.bandstop — Functionbandstop!(t::Trace, f1, f2; poles=2, twopass=false, kind=DSP.Butterworth(poles)) -> t
bandstop(t::Trace, f1, f2; poles=2, twopass=false, kind=DSP.Butterworth(poles)) -> t′Apply a bandreject filter to the trace t with stop band between frequencies f1 and f2 in Hz. In the first form, update the trace in place and return it. In the second form, return an updated copy.
Optionally specify the number of poles of the filter, and whether a two-pass filter should be applied. This doubles the effective number of poles, because both a forward and reverse pass occur. This has the advantage of preserving the phase.
Specify the kind of filter by providing a kind from the DSP.Filters module. If doing so, the poles keyword argument is not used and the number of poles, ripple power, etc., should be specified when providing the filter kind.
Seis.bandpass! — Functionbandpass!(t::Trace, f1, f2; poles=2, twopass=false) -> t
bandpass(t::Trace, f1, f2; poles=2, twopass=false) -> t′Apply a bandpass filter to the trace t between frequencies f1 and f2 in Hz. In the first form, update the trace in place and return it. In the second form, return an updated copy.
Optionally specify the number of poles of the filter, and whether a two-pass filter should be applied. This doubles the effective number of poles, because both a forward and reverse pass occur. This has the advantage of preserving the phase.
Specify the kind of filter by providing a kind from the DSP.Filters module. If doing so, the poles keyword argument is not used and the number of poles, ripple power, etc., should be specified when providing the filter kind.
Seis.bandpass — Functionbandpass!(t::Trace, f1, f2; poles=2, twopass=false) -> t
bandpass(t::Trace, f1, f2; poles=2, twopass=false) -> t′Apply a bandpass filter to the trace t between frequencies f1 and f2 in Hz. In the first form, update the trace in place and return it. In the second form, return an updated copy.
Optionally specify the number of poles of the filter, and whether a two-pass filter should be applied. This doubles the effective number of poles, because both a forward and reverse pass occur. This has the advantage of preserving the phase.
Specify the kind of filter by providing a kind from the DSP.Filters module. If doing so, the poles keyword argument is not used and the number of poles, ripple power, etc., should be specified when providing the filter kind.
Seis.highpass! — Functionhighpass!(t::Trace, f; poles=2, twopass=false, kind=DSP.Butterworth(poles)) -> t
highpass(t::Trace, f; poles=2, twopass=false, kind=DSP.Butterworth(poles)) -> t′Apply a highpass filter to the trace t with corner frequency f in Hz. In the first form, update the trace in place and return it. In the second form, return an updated copy.
Optionally specify the number of poles of the filter, and whether a two-pass filter should be applied. This doubles the effective number of poles, because both a forward and reverse pass occur. This has the advantage of preserving the phase.
Specify the kind of filter by providing a kind from the DSP.Filters module. If doing so, the poles keyword argument is not used and the number of poles, ripple power, etc., should be specified when providing the filter kind.
Seis.highpass — Functionhighpass!(t::Trace, f; poles=2, twopass=false, kind=DSP.Butterworth(poles)) -> t
highpass(t::Trace, f; poles=2, twopass=false, kind=DSP.Butterworth(poles)) -> t′Apply a highpass filter to the trace t with corner frequency f in Hz. In the first form, update the trace in place and return it. In the second form, return an updated copy.
Optionally specify the number of poles of the filter, and whether a two-pass filter should be applied. This doubles the effective number of poles, because both a forward and reverse pass occur. This has the advantage of preserving the phase.
Specify the kind of filter by providing a kind from the DSP.Filters module. If doing so, the poles keyword argument is not used and the number of poles, ripple power, etc., should be specified when providing the filter kind.
Seis.lowpass! — Functionlowpass!(t::Trace, f; poles=2, twopass=false, kind=DSP.Butterworth(poles)) -> t
lowpass(t::Trace, f; poles=2, twopass=false, kind=DSP.Butterworth(poles)) -> t′Apply a lowpass filter to the trace t with corner frequency f in Hz. In the first form, update the trace in place and return it. In the second form, return an updated copy.
Optionally specify the number of poles of the filter, and whether a two-pass filter should be applied. This doubles the effective number of poles, because both a forward and reverse pass occur. This has the advantage of preserving the phase.
Specify the kind of filter by providing a kind from the DSP.Filters module. If doing so, the poles keyword argument is not used and the number of poles, ripple power, etc., should be specified when providing the filter kind.
Seis.lowpass — Functionlowpass!(t::Trace, f; poles=2, twopass=false, kind=DSP.Butterworth(poles)) -> t
lowpass(t::Trace, f; poles=2, twopass=false, kind=DSP.Butterworth(poles)) -> t′Apply a lowpass filter to the trace t with corner frequency f in Hz. In the first form, update the trace in place and return it. In the second form, return an updated copy.
Optionally specify the number of poles of the filter, and whether a two-pass filter should be applied. This doubles the effective number of poles, because both a forward and reverse pass occur. This has the advantage of preserving the phase.
Specify the kind of filter by providing a kind from the DSP.Filters module. If doing so, the poles keyword argument is not used and the number of poles, ripple power, etc., should be specified when providing the filter kind.
Trace rotation
Seis.rotate_through! — Functionrotate_through!(t1::Trace, t2::Trace, phi)For two traces t1 an t2 which are horizontal and orthgonal, rotate them clockwise by phi° about the vertical axis.
This is a reference frame transformation (passive rotation) and hence particle motion will appear to rotate anti-clockwise.
Seis.rotate_through — Functionrotate_through!(t1::Trace, t2::Trace, phi)For two traces t1 an t2 which are horizontal and orthgonal, rotate them clockwise by phi° about the vertical axis.
This is a reference frame transformation (passive rotation) and hence particle motion will appear to rotate anti-clockwise.
Seis.rotate_to_gcp! — Functionrotate_to_gcp!(t1, t2; reverse=false) -> t1, t2Rotate the pair of traces t1 and t2 in place so that t1 points along the radial direction (the backazimuth plus 180°), and t2 is 90° clockwise from that.
If reverse is true, then t2 is rotated to be 90° anticlockwise from t1, so that the polarity is reversed.
The component names of the radial and transverse traces are updated to be 'R', and either 'T' or '-T' respectively for normal and reverse polarity, unless the component code is a valid SEED identifier which seems rotatable and matches for the traces; then the correct component name is used. (E.g., "BHE" and "BHN" become "BHR" and "BHT".)
Traces must be orthogonal and horizontal.
rotate_to_gcp!(t::AbstractArray{T); kwargs...)Rotate pairs of traces in the array t so they are in the order [R1, T1, R2, T2, ...].
Seis.rotate_to_gcp — Functionrotate_to_gcp(t1, t2; reverse=false) -> R, T
rotate_to_gcp(t::AbstractArray{<:AbstractTrace}; reverse=false) -> t′Copying version of rotate_to_gcp! which returns the radial R and transverse T traces in the first form, or pairs of radial and transverse traces in the modified array t′
IO
Seis.read_mseed — Functionread_mseed(file; kwargs...) -> traces
read_mseed(T, file; kwargs...) -> traces::Vector{T}Read a single miniseed file from disk and return a set of Traces.
The meta.mseed_file field of each trace contains the file name.
Optionally specify the type of trace T <: AbstractTrace to read. By default, T is Trace{Float32, Vector{Float32}, Geographic{Float32}}, since almost all seismic data stored in Miniseed format is single-precision.
Example
Read a single file:
julia> read_mseed("data.mseed")Read a single file assuming a Cartesian geometry:
julia> read_mseed(CartTrace{Float32, Vector{Float32}}, "data.mseed")Using a float type of Float64 for T (e.g., Trace{Float64, Vector{Float64}, Seis.Geographic{Float32}}}) will not increase the precision of data read, since the current implementation of Miniseed reading converts 64-bit data into 32-bit data.
Handling gapped/overlapped data
When channels containing gaps or overlaps are encountered, they are split into multiple Traces as each Trace must be continuous and evenly sampled. However, data quite often contain single-sample offsets which are later corrected, and so these are ignored by default.
Use the keyword arguments maximum_gap and maximum_offset to control whether or not gaps cause new traces to be created. See below for more details.
Keyword arguments
The following keyword arguments can be passed to read_mseed:
maximum_gap: The maximum absolute gap length in s beyond which gaps are no longer tolerated in a single trace. By default this is the sampling interval of the trace being read.Note Set
maximum_gapto 0 to always split miniseed files into separate traces at all gaps.maximum_offset: The maximum sum of all gaps beyond which gaps are no longer tolerated in a single trace. This is calculated by simply adding all the gaps together. By default this is the sampling interval.
read_mseed([T,] data::Vector{UInt8}; kwargs...) -> tracesRead Miniseed data from memory, held as a set of bytes, optionally specifying the type T of traces to return. Keyword arguments are the same as for reading from a file on disk.
read_mseed(pattern, dir) -> ::Vector{<:Trace}
read_mseed(T, pattern, dir) -> Vector{T}Read all files matching pattern in directory dir.
See Glob.glob for details of pattern matching.
Optionally specify the type of trace T <: AbstractTrace to read. By default, T is Trace{Float32, Vector{Float32}, Geographic{Float32}}, since almost all seismic data stored in Miniseed format is single-precision.
Example
Read all files matching "TA.*.BHZ.mseed" in all directories within DATA which themselves match "Event_??":
julia> read_mseed("Event_??/TA.*.BHZ.mseed", "DATA")Seis.read_sac — Functionread_sac(file; terse=false, header_only=true) → ::TraceRead a single evenly-sampled SAC file and return a Trace. If terse is true, then warn when auto-byteswapping files. To read only SAC headers from files, returning an empty trace, set header_only to `true.
read_sac(glob, dir; echo=true, header_only=false) → ::Vector{Trace}Read SAC files which match the patern glob in directory dir and return a set of Traces. Add the file names to t.meta.file. These are relative paths.
File names matching the pattern are shown unless echo is false.
When reading SAC files, the following conventions are observed:
- The event id is held in header
KEVNM - Channel ID is held in
KCMPNM - Location ID is held in
KHOLE - If
Oand the file origin time parameters are set,Ois shifted to 0 time, and all time picks are adjusted. This is similar to using the commandsch o gmt [date]; ch allt (0 - &1,o&)to set the origin in SAC. - Time picks are added to the
Tracepicks.
SAC headers which don't directly translate to Trace attributes are placed in the .meta field and have names prefixed by "SAC_".
Seis.write_sac — Functionwrite_sac(t, file; littleendian=false)Write the Trace t to file in SAC format.
Keys in the t.meta field which begin with SAC_ have their values written to the corresponding SAC field (e.g., t.meta.SAC_kuser0 is written to the KUSER0 header). The user is responsible for ensuring that the values corresponding to these keys can be converted to the correct header type. Note also that SAC_ meta fields override the equivalent Trace headers (e.g., t.sta.sta is equivalent to SAC_kstnm) and so one way to override the values in Trace headers is to set the SAC_ fields. Note that the header is lowercase (i.e., SAC_kstnm not SAC_KSTNM).
Time picks with keys corresponding to SAC picks headers (A, F, and T0 to T9) are transferred, but other picks are not.
If t is in a Cartesian reference frame (i.e., its positions are given by CartEvent and CartStation), then the Cartesian station coordinates x, y and z are saved respectively to headers USER0, USER1 and USER2. Likewise, the event coordinates are saved respectively to USER3, USER4 and USER5. Any information in meta fields SAC_user0 to SAC_user5 will overwrite this data.
The convention on how non-geographic coordinates are written in SAC headers is not part of the API and may change at any time. Saving non-standard information in SAC headers should be done explicitly by the user if this information is important.
By default, files are written to disk in bigendian format (MacSAC or SAC/BRIS convention). Use littleendian=true to write in littleendian byte order (SAC/IRIS or SAC2000 convention).
Seis.SAC.SACTrace — TypeSACTrace(delta, npts, b=0.) -> ::SACTraceConstruct a composite type holding an evenly-spaced SAC time-series trace, where the trace is accessed through the field name t. Supply the constant sampling interval delta in seconds, and the number of points in the trace t. Optionally, specify the trace start time b in seconds.
SACTrace(v::AbstractVector, delta, b=0.) -> ::SACTraceConstruct a SACTrace by supplying an array v, sampling interval delta and optionally the starting time.
SACTrace(d::Vector{UInt8}, file=""; swap=true, terse=false, check_npts=true) -> ::SACTraceConstruct a SACTrace from a raw array of bytes representing some data in SAC format. If swap is false, then non-native-endian files are not converted. If terse is true, then warnings about swapping are not written. If check_npts is false, then parts of files are read without error.
Example data sets
Seis.sample_data — Functionsample_data() -> ::Trace
sample_data(kind::Symbol) -> ::Array{Trace}Return some sample data.
With no arguments, sample gives one trace from a local earthquake recorded in California.
In the second form, a set of traces is returned according to the table below:
kind | Description |
|---|---|
:local | Livermore Valley, CA. 9 3-component stations |
:regional | Nevada. 4 3-component stations |
:teleseism | Mid-period recording of Eureka, CA event. 4 3-c stations |
:teleseisl | Long-period recording of Eureka, CA event. 4 3-c stations |
:array | Deep Fiji event. 60 vertical stations in the UK |