Tutorial

Example Data Set

For the time being we will attempt to curate an up-to-date example data set which you can use to get started. Download it here (220 MB).

Learning Python and ObsPy

pyasdf is written in Python and utilizes the data structures of ObsPy to allow the construction of modern and efficient workflows. Python is an easy to learn and powerful interactive programming language with an exhaustive scientific ecosystem. The following resources are useful if you are starting out with Python and ObsPy:

Using pyasdf

This section will teach you the basics of creating and working with ASDF files with pyasdf. For more detailed information, please see the API documentation or have a look at the Examples section that demonstrates more complex workflows.

Notes on using MPI

pyasdf will behave slightly different depending on whether it is being called with MPI or not. If called with MPI, the underlying HDF5 files will be opened with MPI I/O and fully parallel I/O will be utilized for the processing functions. Keep the scripts reasonably short if using MPI or place appropriate barriers.

The module will detect if it has been called with MPI if mpi4py can be imported and the size of the communicator is greater than one. Thus calling it with mpirun/mpiexec with only one core will not be recognized as being called with MPI.

Due to a limitation of Python you should always delete all references to the ASDFDataSet objects at the end. Otherwise the program will potentially not finish when called with MPI. An even better alternative is described in Usage as a Context Manager.

Creating an ASDF data set

Initialization

The first step is always to import pyasdf and create a ASDFDataSet object. If the file does not exists, it will be created, otherwise the existing one will be opened.

>>> import pyasdf
>>> ds = pyasdf.ASDFDataSet("new_file.h5", compression="gzip-3")

Compression will help to reduce the size of files without affecting the quality as all offered compression options are lossless. Only new data will be compressed and compression will be disable for files created with parallel I/O as these two features are not compatible. See the documentation of the ASDFDataSet object for more details.

At any point you can get an overview of the contents by printing the object

>>> print(ds)
ASDF file [format version: 1.0.0]: 'new_file.h5' (7.7 KB)
Contains 0 event(s)
Contains waveform data from 0 station(s).

Adding Information about an Earthquake

ASDF can optionally store events and associate waveforms with a given event. To add an event with pyasdf use the add_quakeml() method. Be aware that all operations will directly write to the file without an explicit save/write step. This enables pyasdf to deal with arbitrarily big data sets.

>>> ds.add_quakeml("/path/to/quake.xml")
>>> print(ds)
ASDF file [format version: 1.0.0]: 'new_file.h5' (14.7 KB)
Contains 1 event(s)
Contains waveform data from 0 station(s).

The event can later be accessed again by using the event attribute. Please be careful that this might contain multiple events and not only one.

>>> event = ds.events[0]

Adding Waveforms

The next step is to add waveform data. In this example we will add all SAC files in one folder with the help of the add_waveforms() method. Printing the progress is unnecessary but useful when dealing with large amounts of data. There are a couple of subtleties to keep in mind here:

  • The data will be compressed with the compression settings given during the initialization of the data set object.

  • It is possible to optionally associate waveforms with a specific event.

  • You must give a tag. The tag is an additional identifier of that particular waveform. The "raw_recording" tag is by convention only given to raw, unprocessed data.

  • The actual type of the data will not change. This example uses SAC which means data is in single precision floating point, MiniSEED will typically be in single precision integer if coming from a data center. If you desire a different data type to be stored for whatever reason you have to manually convert it and pass the ObsPy Stream object.

>>> import glob
>>> files = glob.glob("/path/to/data/*.mseed")
>>> for _i, filename in enumerate(files):
...     print("Adding file %i of %i ..." % (_i + 1, len(files)))
...     ds.add_waveforms(filename, tag="raw_recording", event_id=event)
Adding file 1 of 588 ...
...
>>> print(ds)
ASDF file [format version: 1.0.0]: 'new_file.h5' (169.7 MB)
Contains 1 event(s)
Contains waveform data from 196 station(s).

Adding Station Information

The last step to create a very basic ASDF file is to add station information which is fairly straightforward.

Note

Please keep in mind that this will potentially rearrange and split the StationXML files to fit within the structure imposed by the ASDF format. StationXML can store any number and combination of networks, stations, and channels whereas ASDF requires a separate StationXML file per station. pyasdf will thus split up files if necessary and also merge them with any possibly already existing StationXML files.

>>> files = glob.glob("/path/to/stations/*.xml")
>>> for _i, filename in enumerate(files):
...     print("Adding file %i of %i ..." % (_i + 1, len(files)))
...     ds.add_stationxml(filename)
Adding file 1 of 196 ...
...
>>> print(ds)
ASDF file [format version: 1.0.0]: 'new_file.h5' (188.3 MB)
Contains 1 event(s)
Contains waveform data from 196 station(s).

Adding Auxiliary Data

The ASDF format has the capability to store generic non-waveform data called auxiliary data. Auxiliary data are data arrays with associcated attributes that can represent anything; each sub-community is supposed to come up with conventions of how to use this.

>>> import numpy as np
>>> data = np.random.random(100)
# The type always should be camel case.
>>> data_type = "RandomArrays"
# Name to identify the particular piece of data.
>>> path = "example_array"
# Any additional parameters as a Python dictionary which will end up as
# attributes of the array.
>>> parameters = {
...     "a": 1,
...     "b": 2.0}
>>> ds.add_auxiliary_data(data=data, data_type=data_type, path=path,
...                       parameters=parameters)
>>> print(ds)
ASDF file [format version: '1.0.0']: 'new_file.h5' (188.3 MB)
Contains 1 event(s)
Contains waveform data from 196 station(s).
Contains 1 type(s) of auxiliary data: RandomArrays

Reading an existing ASDF data set

Once you have acquired an ASDF file by whatever means it is time to read the data. To a large extent reading works by attribute access (meaning tab completion in interactive environments is available). At access time the data is read from an ASDF file an parsed to an ObsPy object.

As always, the first step is to open a file. Note that this does not yet read any data.

>>> import pyasdf
>>> ds = pyasdf.ASDFDataSet("example.h5")

Reading Events

To read event data, simply access the event attribute. At access time the events will be parsed to an obspy.core.event.Catalog object which can used for further analysis.

>>> type(ds.events)
obspy.core.event.Catalog
>>> print(ds.events)
4 Event(s) in Catalog:
1998-09-01T10:29:54.500000Z | -58.500,  -26.100 | 5.5 Mwc
2012-04-04T14:21:42.300000Z | +41.818,  +79.689 | 4.4 mb | manual
2012-04-04T14:18:37.000000Z | +39.342,  +41.044 | 4.3 ML | manual
2012-04-04T14:08:46.000000Z | +38.017,  +37.736 | 3.0 ML | manual

Reading Waveforms and StationXML

Waveforms and station meta information can be accessed at a per-station granularity under the waveforms attribute. Note that tab completion works everywhere so please play around in the IPython shell which is the best way to learn how to use pyasdf.

In the following we will access the data for the IU.ANMO station. Note that the dot is replaced by an underscore to work around syntax limitations imposed by Python. Once again, at attribute access everything is read from the ASDF file and parsed to an ObsPy object.

>>> print(ds.waveforms.IU_ANMO)
Contents of the data set for station IU.ANMO:
    - Has a StationXML file
    - 2 Waveform Tag(s):
        observed_processed
        synthetic)

>>> type(ds.waveform.IU_ANMO.StationXML))
obspy.core.inventory.inventory.Inventory
>>> print(ds.waveform.IU_ANMO.StationXML)
Inventory created at 2014-12-10T17:04:09.000000Z
Created by: IRIS WEB SERVICE: fdsnws-station | version: 1.1.9
        http://service.iris.edu/fdsnws/station/1/query?network=IU&level=res...
Sending institution: IRIS-DMC (IRIS-DMC)
Contains:
    Networks (1):
        IU
    Stations (1):
        IU.ANMO (Albuquerque, New Mexico, USA)
    Channels (6):
        IU.ANMO..BH1, IU.ANMO..BH2, IU.ANMO..BHU, IU.ANMO..BHV,
        IU.ANMO..BHW, IU.ANMO..BHZ

>>> type(ds.waveforms.IU_ANMO.synthetic)
obspy.core.stream.Stream
>>> print(ds.waveforms.IU_ANMO.synthetic)
3 Trace(s) in Stream:
IU.ANMO.S3.MXE | 1998-09-01T10:29:52.250000Z - 1998-09-01T12:10:19.857558Z | 7.0 Hz, 42300 samples
IU.ANMO.S3.MXN | 1998-09-01T10:29:52.250000Z - 1998-09-01T12:10:19.857558Z | 7.0 Hz, 42300 samples
IU.ANMO.S3.MXZ | 1998-09-01T10:29:52.250000Z - 1998-09-01T12:10:19.857558Z | 7.0 Hz, 42300 samples

Now attribute access is convenient for interactive use, but not that much for programmatic access. A number of better ways are available for that case:

>>> ds.waveforms.list()
['IU.ADK', 'IU.AFI', 'IU.ANMO', 'IU.ANTO', 'IU.BBSR']

>>> print(ds.waveforms["IU.ANMO"])
Contents of the data set for station IU.ANMO:
    - Has a StationXML file
    - 2 Waveform Tag(s):
        observed_processed
        synthetic)

>>> for station in ds.waveforms:
...     print(station)
...     break
Contents of the data set for station IU.ADK:
    - Has a StationXML file
    - 2 Waveform Tag(s):
        observed_processed
        synthetic)

The object returned for each station is just a helper object easing the access to the waveform and station data.

>>> sta = ds.waveforms["IU.ANMO"]
>>> type(sta)
pyasdf.utils.WaveformAccessor

ASDF distinguishes waveforms by tags. All waveforms belonging to a certain tag can be accessed with either attribute or key access.

>>> print(sta.synthetic)
3 Trace(s) in Stream:
IU.ANMO.S3.MXE | 1998-09-01T10:29:52.250000Z - 1998-09-01T12:10:19.857558Z | 7.0 Hz, 42300 samples
IU.ANMO.S3.MXN | 1998-09-01T10:29:52.250000Z - 1998-09-01T12:10:19.857558Z | 7.0 Hz, 42300 samples
IU.ANMO.S3.MXZ | 1998-09-01T10:29:52.250000Z - 1998-09-01T12:10:19.857558Z | 7.0 Hz, 42300 samples
>>> sta.synthetic == sta["synthetic"]
True

Get a list of all tags for a certain station:

>>> sta.get_waveform_tags()
['observed_processed', 'synthetic']

Sometimes more granular access is required. To that end one can also access waveforms at the individual trace level.

>>> sta.list()
['IU.ANMO..BHZ__1998-09-01T10:24:49__1998-09-01T12:09:48__observed_processed',
 'IU.ANMO.S3.MXE__1998-09-01T10:29:52__1998-09-01T12:10:19__synthetic',
 'IU.ANMO.S3.MXN__1998-09-01T10:29:52__1998-09-01T12:10:19__synthetic',
 'IU.ANMO.S3.MXZ__1998-09-01T10:29:52__1998-09-01T12:10:19__synthetic',
 'StationXML']
>>> print(sta["IU.ANMO.S3.MXE__1998-09-01T10:29:52__1998-09-01T12:10:19__synthetic"])
1 Trace(s) in Stream:
IU.ANMO.S3.MXE | 1998-09-01T10:29:52.250000Z - 1998-09-01T12:10:19.857558Z | 7.0 Hz, 42300 samples

The advantage of the ASDF format is that it is also able to store relations so it can for example tell what event a certain waveform is associated with:

>>> cat = ds.events  # The events have to be in memory for the reference to work.
>>> print(sta.synthetic[0].stats.asdf.event_ids[0].get_referred_object())
Event:      1998-09-01T10:29:54.500000Z | -58.500,  -26.100 | 5.5 Mwc

        resource_id: ResourceIdentifier(id="smi:service.iris.edu/fdsnws/event/1/query?eventid=656970")
         event_type: 'earthquake'
---------
 event_descriptions: 1 Elements
   focal_mechanisms: 1 Elements
            origins: 1 Elements
         magnitudes: 1 Elements

Additionally it can also store the provenance associated with a certain waveform trace:

>>> prov_id = sta.synthetic[0].stats.asdf.provenance_id
>>> ds.provenance.get_provenance_document_for_id(prov_id)
{'document': <ProvDocument>, 'name': '373da5fe_d424_4f44_9bca_4334d77ed10b'}
>>> ds.provenance.get_provenance_document_for_id(prov_id)["document"].plot()
digraph G { graph [bb="0,0,1480,925.94", charset="utf-8", rankdir=BT ]; node [label="\N"]; n1 [URL="http://seisprov.org/seis_prov/0.1/#sp000_pp_dj89345j", fillcolor="#FED37F", height=0.77692, label=<Hans Mustermann<br /><font color="#333333" point-size="10">seis_prov:sp000_pp_dj89345j</font>>, pos="206,897.97", shape=house, style=filled, width=3.3154]; ann1 [color=gray, fontcolor=black, fontsize=10, height=0.80556, label=<<TABLE cellpadding="0" border="0"> <TR> <TD align="left" href="http://www.w3.org/ns/prov#label">prov:label</TD> <TD align="left">Hans Mustermann</TD> </TR> <TR> <TD align="left" href="http://www.w3.org/ns/prov#type">prov:type</TD> <TD align="left" href="http://www.w3.org/ns/prov#Person">prov:Person</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#email">seis_prov:email</TD> <TD align="left">hans.mustermann@email.com</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#name">seis_prov:name</TD> <TD align="left">Hans Mustermann</TD> </TR> </TABLE>>, pos="103,804", shape=note, width=2.8611]; ann1 -> n1 [arrowhead=none, color=gray, pos="134.46,833.09 149.61,846.62 167.49,862.59 181.59,875.17", style=dashed]; n2 [URL="http://seisprov.org/seis_prov/0.1/#sp000_pp_9034j90df", fillcolor="#FED37F", height=0.77692, label=<Susanna Musterfrau<br /><font color="#333333" point-size="10">seis_prov:sp000_pp_9034j90df</font>>, pos="348,804", shape=house, style=filled, width=3.4502]; ann2 [color=gray, fontcolor=black, fontsize=10, height=0.80556, label=<<TABLE cellpadding="0" border="0"> <TR> <TD align="left" href="http://www.w3.org/ns/prov#label">prov:label</TD> <TD align="left">Susanna Musterfrau</TD> </TR> <TR> <TD align="left" href="http://www.w3.org/ns/prov#type">prov:type</TD> <TD align="left" href="http://www.w3.org/ns/prov#Person">prov:Person</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#email">seis_prov:email</TD> <TD align="left">susanna.musterfrau@email.com</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#name">seis_prov:name</TD> <TD align="left">Susanna Musterfrau</TD> </TR> </TABLE>>, pos="222,694", shape=note, width=2.9583]; ann2 -> n2 [arrowhead=none, color=gray, pos="254.78,723.09 275.92,741.22 303.02,764.45 322.55,781.18", style=dashed]; n3 [URL="http://seisprov.org/seis_prov/0.1/#sp000_sa_9dig8ata", fillcolor="#FED37F", height=0.77692, label=<SPECFEM3D GLOBE<br /><font color="#333333" point-size="10">seis_prov:sp000_sa_9dig8ata</font>>, pos="495,694", shape=house, style=filled, width=3.533]; b3 [color=gray, height=0.05, label="", pos="493,804", shape=point, width=0.05]; n3 -> b3 [arrowhead=none, color="#FED37F", fontsize=10.0, label=actedOnBehalfOf, lp="529.26,752", pos="494.5,721.97 493.95,751.46 493.14,795.44 493.02,802.13"]; ann3 [color=gray, fontcolor=black, fontsize=10, height=0.97222, label=<<TABLE cellpadding="0" border="0"> <TR> <TD align="left" href="http://www.w3.org/ns/prov#label">prov:label</TD> <TD align="left">SPECFEM3D GLOBE</TD> </TR> <TR> <TD align="left" href="http://www.w3.org/ns/prov#type">prov:type</TD> <TD align="left" href="http://www.w3.org/ns/prov#SoftwareAgent">prov:SoftwareAgent</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#software_name">seis_prov:software_name</TD> <TD align="left">SPECFEM3D GLOBE</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#software_version">seis_prov:software_version</TD> <TD align="left">7.0.0</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#website">seis_prov:website</TD> <TD align="left">http://geodynamics.org/cig/software/specfem3d</TD> </TR> </TABLE>>, pos="650,578", shape=note, width=4.4583]; ann3 -> n3 [arrowhead=none, color=gray, pos="603.49,613.2 577.81,632.09 546.7,654.98 524.38,671.39", style=dashed]; n4 [URL="http://seisprov.org/seis_prov/0.1/#sp000_em_skfusjdoej", color="#808080", fillcolor="#FFFC87", height=0.62854, label=<Earth Model<br /><font color="#333333" point-size="10">seis_prov:sp000_em_skfusjdoej</font>>, pos="348,578", shape=oval, style=filled, width=2.8348]; b2 [color=gray, height=0.05, label="", pos="348,694", shape=point, width=0.05]; n4 -> b2 [arrowhead=none, color="#FED37F", fontsize=10.0, label=wasAssociatedWith, lp="387.51,636", pos="348,600.71 348,631.2 348,683.91 348,691.96"]; ann4 [color=gray, fontcolor=black, fontsize=10, height=0.97222, label=<<TABLE cellpadding="0" border="0"> <TR> <TD align="left" href="http://www.w3.org/ns/prov#label">prov:label</TD> <TD align="left">Earth Model</TD> </TR> <TR> <TD align="left" href="http://www.w3.org/ns/prov#type">prov:type</TD> <TD align="left">seis_prov:earth_model</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#model_name">seis_prov:model_name</TD> <TD align="left">Random Model</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#model_type">seis_prov:model_type</TD> <TD align="left">3D</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#website">seis_prov:website</TD> <TD align="left">http://random.org/model</TD> </TR> </TABLE>>, pos="348,342", shape=note, width=2.9306]; ann4 -> n4 [arrowhead=none, color=gray, pos="348,377.03 348,425.83 348,514.31 348,555.2", style=dashed]; n5 [URL="http://seisprov.org/seis_prov/0.1/#sp000_in_38jd89da8l", color="#808080", fillcolor="#FFFC87", height=0.62854, label=<Input Parameters<br /><font color="#333333" point-size="10">seis_prov:sp000_in_38jd89da8l</font>>, pos="1300,578", shape=oval, style=filled, width=2.824]; b4 [color=gray, height=0.05, label="", pos="1165,694", shape=point, width=0.05]; n5 -> b4 [arrowhead=none, fontsize=10.0, label=wasDerivedFrom, lp="1235.7,636", pos="1255.1,598.41 1228.7,611.91 1196.5,632.29 1176,659 1167.5,670.02 1165.5,687.79 1165.1,692.06"]; ann5 [color=gray, fontcolor=black, fontsize=10, height=4.3056, label=<<TABLE cellpadding="0" border="0"> <TR> <TD align="left" href="http://www.w3.org/ns/prov#label">prov:label</TD> <TD align="left">Input Parameters</TD> </TR> <TR> <TD align="left" href="http://www.w3.org/ns/prov#type">prov:type</TD> <TD align="left">seis_prov:input_parameters</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#ABSORBING_CONDITIONS">seis_prov:ABSORBING_CONDITIONS</TD> <TD align="left">False</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#ANGULAR_WIDTH_ETA_IN_DEGREES">seis_prov:ANGULAR_WIDTH_ETA_IN_DEGREES</TD> <TD align="left">90.0</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#ANGULAR_WIDTH_XI_IN_DEGREES">seis_prov:ANGULAR_WIDTH_XI_IN_DEGREES</TD> <TD align="left">90.0</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#ANISOTROPIC_KL">seis_prov:ANISOTROPIC_KL</TD> <TD align="left">False</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#ATTENUATION">seis_prov:ATTENUATION</TD> <TD align="left">False</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#CENTER_LATITUDE_IN_DEGREES">seis_prov:CENTER_LATITUDE_IN_DEGREES</TD> <TD align="left">40.0</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#CENTER_LONGITUDE_IN_DEGREES">seis_prov:CENTER_LONGITUDE_IN_DEGREES</TD> <TD align="left">10.0</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#ELLIPTICITY">seis_prov:ELLIPTICITY</TD> <TD align="left">False</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#EXACT_MASS_MATRIX_FOR_ROTATION">seis_prov:EXACT_MASS_MATRIX_FOR_ROTATION</TD> <TD align="left">False</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#GAMMA_ROTATION_AZIMUTH">seis_prov:GAMMA_ROTATION_AZIMUTH</TD> <TD align="left">20.0</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#GRAVITY">seis_prov:GRAVITY</TD> <TD align="left">False</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#NCHUNKS">seis_prov:NCHUNKS</TD> <TD align="left">1</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#NEX_ETA">seis_prov:NEX_ETA</TD> <TD align="left">240</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#NEX_XI">seis_prov:NEX_XI</TD> <TD align="left">240</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#NOISE_TOMOGRAPHY">seis_prov:NOISE_TOMOGRAPHY</TD> <TD align="left">0</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#NPROC_ETA">seis_prov:NPROC_ETA</TD> <TD align="left">5</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#NPROC_XI">seis_prov:NPROC_XI</TD> <TD align="left">5</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#OCEANS">seis_prov:OCEANS</TD> <TD align="left">False</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#RECEIVERS_CAN_BE_BURIED">seis_prov:RECEIVERS_CAN_BE_BURIED</TD> <TD align="left">True</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#ROTATION">seis_prov:ROTATION</TD> <TD align="left">False</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#SIMULATION_TYPE">seis_prov:SIMULATION_TYPE</TD> <TD align="left">1</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#TOPOGRAPHY">seis_prov:TOPOGRAPHY</TD> <TD align="left">False</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#USE_LDDRK">seis_prov:USE_LDDRK</TD> <TD align="left">False</TD> </TR> </TABLE>>, pos="1300,342", shape=note, width=5]; ann5 -> n5 [arrowhead=none, color=gray, pos="1300,497.12 1300,519.89 1300,540.56 1300,555.16", style=dashed]; n6 [URL="http://seisprov.org/seis_prov/0.1/#sp000_fi_d49dh0h4", color="#808080", fillcolor="#FFFC87", height=0.62854, label=<File<br /><font color="#333333" point-size="10">seis_prov:sp000_fi_d49dh0h4</font>>, pos="925,578", shape=oval, style=filled, width=2.6823]; ann6 [color=gray, fontcolor=black, fontsize=10, height=0.97222, label=<<TABLE cellpadding="0" border="0"> <TR> <TD align="left" href="http://www.w3.org/ns/prov#label">prov:label</TD> <TD align="left">File</TD> </TR> <TR> <TD align="left" href="http://www.w3.org/ns/prov#type">prov:type</TD> <TD align="left">seis_prov:file</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#filename">seis_prov:filename</TD> <TD align="left">constants.h</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#location">seis_prov:location</TD> <TD align="left">/AuxiliaryData/Files/constants_h</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#location_type">seis_prov:location_type</TD> <TD align="left">HDF5 Data Set</TD> </TR> </TABLE>>, pos="925,342", shape=note, width=3.4583]; ann6 -> n6 [arrowhead=none, color=gray, pos="925,377.03 925,425.83 925,514.31 925,555.2", style=dashed]; n7 [URL="http://seisprov.org/seis_prov/0.1/#sp000_fi_asf90345", color="#808080", fillcolor="#FFFC87", height=0.62854, label=<File<br /><font color="#333333" point-size="10">seis_prov:sp000_fi_asf90345</font>>, pos="1265,804", shape=oval, style=filled, width=2.6167]; ann7 [color=gray, fontcolor=black, fontsize=10, height=0.97222, label=<<TABLE cellpadding="0" border="0"> <TR> <TD align="left" href="http://www.w3.org/ns/prov#label">prov:label</TD> <TD align="left">File</TD> </TR> <TR> <TD align="left" href="http://www.w3.org/ns/prov#type">prov:type</TD> <TD align="left">seis_prov:file</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#filename">seis_prov:filename</TD> <TD align="left">Parfile</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#location">seis_prov:location</TD> <TD align="left">/AuxiliaryData/Files/Parfile</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#location_type">seis_prov:location_type</TD> <TD align="left">HDF5 Data Set</TD> </TR> </TABLE>>, pos="1299,694", shape=note, width=3.1667]; ann7 -> n7 [arrowhead=none, color=gray, pos="1288.2,729.17 1282.9,746.23 1276.5,766.35 1271.8,781.27", style=dashed]; n8 [URL="http://seisprov.org/seis_prov/0.1/#sp001_wf_4j09fj3", color="#808080", fillcolor="#FFFC87", height=0.62854, label=<Waveform Trace<br /><font color="#333333" point-size="10">seis_prov:sp001_wf_4j09fj3</font>>, pos="486,112", shape=oval, style=filled, width=2.5621]; n9 [URL="http://seisprov.org/seis_prov/0.1/#sp001_ws_f87sf7sf78", color="#0000FF", fillcolor="#9FB1FC", height=0.5, label=<Waveform Simulation<br /><font color="#333333" point-size="10">seis_prov:sp001_ws_f87sf7sf78</font>>, pos="627,342", shape=box, style=filled, width=2.0123]; n8 -> n9 [color=darkgreen, fontcolor=darkgreen, fontsize=10.0, label=wasGeneratedBy, lp="554.15,164", pos="e,616.42,323.89 499.26,134.45 525.3,176.56 583.01,269.86 611.06,315.23"]; ann8 [color=gray, fontcolor=black, fontsize=10, height=0.63889, label=<<TABLE cellpadding="0" border="0"> <TR> <TD align="left" href="http://www.w3.org/ns/prov#label">prov:label</TD> <TD align="left">Waveform Trace</TD> </TR> <TR> <TD align="left" href="http://www.w3.org/ns/prov#type">prov:type</TD> <TD align="left">seis_prov:waveform_trace</TD> </TR> <TR> <TD align="left" href="http://seisprov.org/seis_prov/0.1/#description">seis_prov:description</TD> <TD align="left">Synthetic Waveform</TD> </TR> </TABLE>>, pos="486,23", shape=note, width=2.9583]; ann8 -> n8 [arrowhead=none, color=gray, pos="486,46.405 486,59.595 486,76.201 486,89.272", style=dashed]; n9 -> n4 [color=red4, fontcolor=red, fontsize=10.0, label=used, lp="447.17,520", pos="e,380.14,556.47 610.51,360.04 581.76,389.39 520.05,450.78 463,497 439.31,516.19 411.24,535.77 388.77,550.76"]; n9 -> n5 [color=red4, fontcolor=red, fontsize=10.0, label=used, lp="879.17,520", pos="e,1247.4,558.57 639.2,360.11 663.82,393.11 723,465.1 792,497 953.63,571.72 1015.8,506.33 1190,543 1205.6,546.28 1222.1,550.8 1237.5,\ 555.48"]; n9 -> n6 [color=red4, fontcolor=red, fontsize=10.0, label=used, lp="804.17,520", pos="e,866.89,559.81 638.8,360.15 663.88,395.46 725.94,477 795.67,525 814.34,537.85 836.66,548.26 857.46,556.29"]; b1 [color=gray, height=0.05, label="", pos="470,578", shape=point, width=0.05]; n9 -> b1 [arrowhead=none, color="#FED37F", fontsize=10.0, label=wasAssociatedWith, lp="532.51,520", pos="611.45,360.2 582.21,393.34 518.61,469.28 481,543 474.68,555.38 471,572.13 470.18,576.12"]; ann9 [color=gray, fontcolor=black, fontsize=10, height=0.80556, label=<<TABLE cellpadding="0" border="0"> <TR> <TD align="left" href="http://www.w3.org/ns/prov#startTime">prov:startTime</TD> <TD align="left">2014-02-02T12:15:03</TD> </TR> <TR> <TD align="left" href="http://www.w3.org/ns/prov#endTime">prov:endTime</TD> <TD align="left">2014-02-02T14:07:13</TD> </TR> <TR> <TD align="left" href="http://www.w3.org/ns/prov#label">prov:label</TD> <TD align="left">Waveform Simulation</TD> </TR> <TR> <TD align="left" href="http://www.w3.org/ns/prov#type">prov:type</TD> <TD align="left">seis_prov:waveform_simulation</TD> </TR> </TABLE>>, pos="701,112", shape=note, width=2.9028]; ann9 -> n9 [arrowhead=none, color=gray, pos="691.78,141.42 676.2,189.4 645.15,285.07 632.53,323.97", style=dashed]; b1 -> n3 [color="#FED37F", fontsize=10.0, pos="e,490.21,671.17 470.28,580.28 472.01,588.17 481.37,630.85 488.06,661.36"]; b2 -> n2 [color="#FED37F", fontsize=10.0, pos="e,348,781.11 348,696.21 348,703.52 348,742.32 348,771.06"]; b3 -> n1 [color="#FED37F", fontsize=10.0, pos="e,325.46,880.09 492.91,805.85 492.46,809.66 490.08,825.39 481,833 458.22,852.08 395.33,867.44 335.43,878.32"]; b4 -> n7 [fontsize=10.0, pos="e,1232.2,782.59 1165.1,695.92 1165.6,700.09 1168.2,717.49 1176,729 1188.6,747.59 1207.1,764.05 1224,776.69"]; ann10 [color=gray, fontcolor=black, fontsize=10, height=0.5, label=<<TABLE cellpadding="0" border="0"> <TR> <TD align="left" href="http://www.w3.org/ns/prov#type">prov:type</TD> <TD align="left" href="http://www.w3.org/ns/prov#PrimarySource">prov:PrimarySource</TD> </TR> </TABLE>>, pos="1110,578", shape=note, width=1.9583]; ann10 -> b4 [arrowhead=none, color=gray, pos="1118.4,596.31 1132.5,625.71 1160.2,683.08 1164.5,691.86", style=dashed]; }

Reading Auxiliary Data

ASDF can additionally also store non-waveform data. Access is via the auxiliary_data attribute. Once again, dictionary access is possible.

>>> print(ds.auxiliary_data)
Data set contains the following auxiliary data types:
    AdjointSource (12 item(s))
    File (1 item(s))

>>> print(ds.auxiliary_data.AdjointSource)
print(ds.auxiliary_data.AdjointSource)
12 auxiliary data item(s) of type 'AdjointSource' available:
    BW_ALFO_EHE
    BW_ALFO_EHN
    BW_ALFO_EHZ
    BW_BLA_EHE
    BW_BLA_EHN
    BW_BLA_EHZ
    IU_ANMO_EHE
    IU_ANMO_EHN
    IU_ANMO_EHZ
    TA_A023_BHE
    TA_A023_BHN
    TA_A023_BHZ

>>> ds.auxiliary_data.list()
['AdjointSource', 'File']

>>> ds.auxiliary_data.AdjointSource == ds.auxiliary_data["AdjointSource"]
True

Accessing a single item once again by attribute or key access.

>>> ds.auxiliary_data.AdjointSource.BW_ALFO_EHE
Auxiliary Data of Type 'AdjointSource'
    Path 'BW_ALFO_EHE'
    Provenance ID: '{http://seisprov.org/seis_prov/0.1/#}sp012_as_cd84e87'
    Data shape: '(20000,)', dtype: 'float64'
    Parameters:
        adjoint_source_type: multitaper
        elevation_in_m: 473.232036071
        latitude: 57.9589770294
        local_depth_in_m: 0.0
        longitude: 170.352381909
        misfit_value: 1.45e-05
        orientation: E
        sampling_rate_in_hz: 10.0
        station_id: BW.ALFO..EHE
        units: m

>>> ds.auxiliary_data.AdjointSource.list()
['BW_ALFO_EHE', 'BW_ALFO_EHN', 'BW_ALFO_EHZ', 'BW_BLA_EHE', 'BW_BLA_EHN', 'BW_BLA_EHZ',
 'IU_ANMO_EHE', 'IU_ANMO_EHN', 'IU_ANMO_EHZ', 'TA_A023_BHE', 'TA_A023_BHN', 'TA_A023_BHZ']

>>> ds.auxiliary_data.AdjointSource.BW_ALFO_EHE == ds.auxiliary_data.AdjointSource["BW_ALFO_EHE"]
True

>>> adj_src = ds.auxiliary_data.AdjointSource.BW_ALFO_EHE
>>> adj_src.data
<HDF5 dataset "BW_ALFO_EHE": shape (20000,), type "<f8">
>>> adj_src.parameters
{'adjoint_source_type': 'multitaper',
 'elevation_in_m': 473.23203607130199,
 'latitude': 57.958977029361542,
 'local_depth_in_m': 0.0,
 'longitude': 170.35238190943915,
 'misfit_value': 1.45e-05,
 'orientation': 'E',
 'sampling_rate_in_hz': 10.0,
 'station_id': 'BW.ALFO..EHE',
 'units': 'm'}