User manual

This section describes how to use QuakeML.jl to read and write QuakeML files, and how to create objects which describe sets of seismic events.

Preamble

The following examples all assume that you have first used the module like so:

julia> using QuakeML

Namespace issues

QuakeML.jl deliberately does not export the types it uses by default, since their names follow those in the QuakeML specification, and they are quite generic to seismic processing—for example, Event and Phase. The recommended way to interact with QuakeML.jl in the REPL or in your own packages is to always use the module name (or an alias of it).

For instance, to define an empty set of events, which are held in the type EventParameters, you would write

julia> events = QuakeML.EventParameters()EventParameters
  comment: Array{QuakeML.Comment}((0,))
  event: Array{QuakeML.Event}((0,))
  description: Missing missing
  creation_info: Missing missing
  public_id: QuakeML.ResourceIdentifier
Note

If you really want to bring the QuakeML.jl types into scope without manually importing them, then there is an option. You can do using QuakeML.Types. Note that this API is not yet stable and use of the Types module is recommended only for interactive use or throwaway scripts.

Important types

For a full list of QuakeML types, see Types. The following are a few of the most important when defining one's own catalogues.

  • EventParameters is the root type, and contains one or more Events.
  • An Event defines a known single source of seismic energy, which may contain one or several
  • Origins. Each Origin is one interpretation of the data, potentially containing information about the source location, origin time, focal mechanism, magnitude, and so on.

The types in this package are directly named after those in the QuakeML specification. Similarly, the fields of each type are named to match the names of the attributes and elements of each QuakeML type. Note however that rather than use camel case likeThis for these field names, in this package we use snake case like_this. Therefore translating between the XML and QuakeML.jl representations of things in the specification should be simple.

Sample data

QuakeML.jl comes with a few sample data sets. To access these, you can define the path to them using the pathof function from Base. We will call this path data_dir:

julia> data_dir = joinpath(dirname(dirname(pathof(QuakeML))), "test", "data")"/home/runner/work/QuakeML.jl/QuakeML.jl/test/data"

Reading

On-disk data

To read a set of events from disk, one simply calls QuakeML.read:

julia> nepal_event = QuakeML.read(joinpath(data_dir, "nepal_mw7.2.qml"))EventParameters
  comment: Array{QuakeML.Comment}((0,))
  event: Array{QuakeML.Event}((1,))
  description: Missing missing
  creation_info: QuakeML.CreationInfo
  public_id: QuakeML.ResourceIdentifier

Strings

To read from a String which contains QuakeML, you use QuakeML.readstring:

julia> qml_string = """
                  <?xml version="1.0"?>
                  <quakeml xmlns="http://quakeml.org/xmlns/quakeml/1.2">
                      <eventParameters publicID="smi:local/events/XXX">
                          <event publicID="smi:local/event/A">
                          </event>
                      </eventParameters>
                  </quakeml>
                  """;
julia> events = QuakeML.readstring(qml_string)EventParameters comment: Array{QuakeML.Comment}((0,)) event: Array{QuakeML.Event}((1,)) description: Missing missing creation_info: Missing missing public_id: QuakeML.ResourceIdentifier

Writing

Writing to disk or subtype of IO

To write a set of events to a file on disk, call write(io, events).

julia> write("nepal.xml", nepal_event)

You can easily verify that the file written is identical to the one we read:

julia> QuakeML.read("nepal.xml") == nepal_eventtrue

Converting to a string

To convert a set of events into a String for subsequent processing, first convert the EventParameters object into an XML document, then call string:

julia> string2 = string(quakeml(events))"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<quakeml xmlns=\"http://quakeml.org/xmlns/quakeml/1.2\"><eventParameters publicID=\"smi:local/events/XXX\"><event publicID=\"smi:local/event/A\"/></eventParameters></quakeml>\n"
Note

One could also create a Base.IOBuffer and write to that directly.

Converting to an in-memory XML document

Internally, QuakeML.jl uses EzXML.jl to parse XML strings and create XML objects from EventParameters. If you are happy to use EzXML, you can create an XML document (an EzXML.Document) by calling quakeml on an EventParameters object.

julia> xml = quakeml(nepal_event)EzXML.Document(EzXML.Node(<DOCUMENT_NODE@0x0000000002f42830>))
julia> typeof(xml)EzXML.Document

Accessing fields

In QuakeML.jl, all fields of types are publicly-accessible and part of the API. It is intended that users will directly access and manipulate these fields. Where restrictions on fields exist (for instance, where strings can be only a certain number of characters long, or can only consist of certain characters), these are enforced both upon construction of types and when changing fields (via setproperty!).

For example, to get the coordinate of the Nepal event we read in earlier, you access the fields directly:

julia> nepal_event.event[1]QuakeML.Event
  description: Array{QuakeML.EventDescription}((1,))
  comment: Array{QuakeML.Comment}((0,))
  focal_mechanism: Array{QuakeML.FocalMechanism}((1,))
  amplitude: Array{QuakeML.Amplitude}((0,))
  magnitude: Array{QuakeML.Magnitude}((1,))
  station_magnitude: Array{QuakeML.StationMagnitude}((0,))
  origin: Array{QuakeML.Origin}((2,))
  pick: Array{QuakeML.Pick}((0,))
  preferred_origin_id: QuakeML.ResourceIdentifier
  preferred_magnitude_id: Missing missing
  preferred_focal_mechanism_id: QuakeML.ResourceIdentifier
  type: QuakeML.EventType
  type_certainty: Missing missing
  creation_info: Missing missing
  public_id: QuakeML.ResourceIdentifier

This returns the first Event in the event field. event is a Vector{Event}, and may be empty.

In QuakeML, any Event may have several Origins. Each Origin describes a unique onset time and location of the event. Usually, one of these origins is the 'preferred' origin. Typically, one uses preferred_origin to return this and then uses the origin parameters within the particular Origin.

julia> o = preferred_origin(nepal_event.event[1])QuakeML.Origin
  composite_time: Array{QuakeML.CompositeTime}((0,))
  comment: Array{QuakeML.Comment}((0,))
  origin_uncertainty: Array{QuakeML.OriginUncertainty}((0,))
  arrival: Array{QuakeML.Arrival}((0,))
  time: QuakeML.TimeQuantity
  longitude: QuakeML.RealQuantity
  latitude: QuakeML.RealQuantity
  depth: QuakeML.RealQuantity
  depth_type: Missing missing
  time_fixed: Bool false
  epicenter_fixed: Bool false
  reference_system_id: Missing missing
  method_id: Missing missing
  earth_model_id: Missing missing
  quality: Missing missing
  type: Missing missing
  region: Missing missing
  evaluation_mode: Missing missing
  evaluation_status: Missing missing
  creation_info: Missing missing
  public_id: QuakeML.ResourceIdentifier
julia> lon, lat = o.longitude.value, o.latitude.value(86.08, 27.67)
Note

Note that the longitude and latitude of an Origin are QuakeML.RealQuantitys. As well as the value field which contains the nominal value of the quantity, they can also contain uncertainties. Hence in this case, we needed to access the actual value of longitude like o.longitude.value, and similarly for latitude.

Almost all types (apart from Enumerated types) are mutable structs, which means that their fields can be changed after construction. Almost all types have at least one field which is optional. In QuakeML.jl, these can either take a concrete value, or missing. Hence setting any optional field to missing (like origin.depth = missing) will remove that value.

Where multiple values of a field are allowed (such as the origin field of an Event), these are represented by Vectors, and can be empty.