Time Series Metadata Examples

Metadata can be confusing and a daunting task. Hopefully mt_metadata makes it easier. Here we will demonstrate some use cases.

[1]:
from mt_metadata.timeseries import (
    Auxiliary, Electric, Experiment, Magnetic, Run, Station, Survey
)

Time Series Metadata as a Single Object

mt_metadata was written so that all metadata can reside under a single object. For example, if you have a single station with multiple runs that have multiple channels, you don’t want to carry around a single file for each. Each level of metadata, namely Experiment, Survey, Station, Run have convenience objects to contain a collection of the next level down. For example Experiment.surveys, Survey.stations or Station.runs or Run.channels. This object is a combination of a List and Dictionary, which allows the user to access items in the collection by index or key word. Each level of metadata also has a add_, get_, and remove_ method to add/get/remove an item from the collection. And example below.

Tip: The benefit of having the experiment in a single object is later you can populate an MTH5 with out data, just the metadata.

[2]:
experiment = Experiment()
survey_01 = Survey(id="01")
experiment.add_survey(survey_01)
print(experiment.surveys)
Contents:
------------
        01 = survey:
        citation_dataset.doi = None
        citation_journal.doi = None
        datum = WGS84
        geographic_name = None
        id = 01
        name = None
        northwest_corner.latitude = 0.0
        northwest_corner.longitude = 0.0
        project = None
        project_lead.email = None
        project_lead.organization = None
        release_license = CC0-1.0
        southeast_corner.latitude = 0.0
        southeast_corner.longitude = 0.0
        summary = None
        time_period.end_date = 1980-01-01
        time_period.start_date = 1980-01-01
[3]:
experiment.get_survey("01")
[3]:
{
    "survey": {
        "citation_dataset.doi": null,
        "citation_journal.doi": null,
        "datum": "WGS84",
        "geographic_name": null,
        "id": "01",
        "name": null,
        "northwest_corner.latitude": 0.0,
        "northwest_corner.longitude": 0.0,
        "project": null,
        "project_lead.email": null,
        "project_lead.organization": null,
        "release_license": "CC0-1.0",
        "southeast_corner.latitude": 0.0,
        "southeast_corner.longitude": 0.0,
        "summary": null,
        "time_period.end_date": "1980-01-01",
        "time_period.start_date": "1980-01-01"
    }
}
[4]:
experiment.surveys[0]
[4]:
{
    "survey": {
        "citation_dataset.doi": null,
        "citation_journal.doi": null,
        "datum": "WGS84",
        "geographic_name": null,
        "id": "01",
        "name": null,
        "northwest_corner.latitude": 0.0,
        "northwest_corner.longitude": 0.0,
        "project": null,
        "project_lead.email": null,
        "project_lead.organization": null,
        "release_license": "CC0-1.0",
        "southeast_corner.latitude": 0.0,
        "southeast_corner.longitude": 0.0,
        "summary": null,
        "time_period.end_date": "1980-01-01",
        "time_period.start_date": "1980-01-01"
    }
}
[5]:
experiment.surveys["01"]
[5]:
{
    "survey": {
        "citation_dataset.doi": null,
        "citation_journal.doi": null,
        "datum": "WGS84",
        "geographic_name": null,
        "id": "01",
        "name": null,
        "northwest_corner.latitude": 0.0,
        "northwest_corner.longitude": 0.0,
        "project": null,
        "project_lead.email": null,
        "project_lead.organization": null,
        "release_license": "CC0-1.0",
        "southeast_corner.latitude": 0.0,
        "southeast_corner.longitude": 0.0,
        "summary": null,
        "time_period.end_date": "1980-01-01",
        "time_period.start_date": "1980-01-01"
    }
}

Full Experiment

This example demonstrates how to build an experiment from scratch and how to interogate it.

[6]:
experiment = Experiment()
kwargs = {
    "time_period.start": "2020-01-01T00:00:00+00:00",
    "time_period.end": "2021-01-01T12:00:00+00:00"
}

for survey in ["One", "Two"]:
    survey_obj = Survey(id=survey)
    survey_obj.filters = {}
    for station in ["mt01", "mt02"]:
        station_obj = Station(id=station, **kwargs)
        for run in ["mt01a", "mt01b"]:
            run_obj = Run(id=run, **kwargs)
            for ch in ["ex", "ey"]:
                ch_obj = Electric(component=ch, **kwargs)
                run_obj.add_channel(ch_obj)
            for ch in ["hx", "hy", "hz"]:
                ch_obj = Magnetic(component=ch, **kwargs)
                run_obj.add_channel(ch_obj)
            for ch in ["temperature", "voltage"]:
                ch_obj = Auxiliary(component=ch, **kwargs)
                run_obj.add_channel(ch_obj)
            run_obj.update_time_period()
            station_obj.runs.append(run_obj)
            station_obj.update_time_period()
        survey_obj.stations.append(station_obj)
        survey_obj.update_time_period()
    experiment.surveys.append(survey_obj)

Pick out a channel

To pick out a channel you need to know the survey, station, and run. If you don’t you can figure out what runs, stations, and surveys are available.

[7]:
experiment
[7]:
Experiment Contents
--------------------
Number of Surveys: 2
  Survey ID: One
  Number of Stations: 2
  Number of Filters: 0
  --------------------
    Station ID: mt01
    Number of Runs: 2
    --------------------
      Run ID: mt01a
      Number of Channels: 7
      Recorded Channels: ex, ey, hx, hy, hz, temperature, voltage
      Start: 2020-01-01T00:00:00+00:00
      End:   2021-01-01T12:00:00+00:00
      --------------------
      Run ID: mt01b
      Number of Channels: 7
      Recorded Channels: ex, ey, hx, hy, hz, temperature, voltage
      Start: 2020-01-01T00:00:00+00:00
      End:   2021-01-01T12:00:00+00:00
      --------------------
    Station ID: mt02
    Number of Runs: 2
    --------------------
      Run ID: mt01a
      Number of Channels: 7
      Recorded Channels: ex, ey, hx, hy, hz, temperature, voltage
      Start: 2020-01-01T00:00:00+00:00
      End:   2021-01-01T12:00:00+00:00
      --------------------
      Run ID: mt01b
      Number of Channels: 7
      Recorded Channels: ex, ey, hx, hy, hz, temperature, voltage
      Start: 2020-01-01T00:00:00+00:00
      End:   2021-01-01T12:00:00+00:00
      --------------------
  Survey ID: Two
  Number of Stations: 2
  Number of Filters: 0
  --------------------
    Station ID: mt01
    Number of Runs: 2
    --------------------
      Run ID: mt01a
      Number of Channels: 7
      Recorded Channels: ex, ey, hx, hy, hz, temperature, voltage
      Start: 2020-01-01T00:00:00+00:00
      End:   2021-01-01T12:00:00+00:00
      --------------------
      Run ID: mt01b
      Number of Channels: 7
      Recorded Channels: ex, ey, hx, hy, hz, temperature, voltage
      Start: 2020-01-01T00:00:00+00:00
      End:   2021-01-01T12:00:00+00:00
      --------------------
    Station ID: mt02
    Number of Runs: 2
    --------------------
      Run ID: mt01a
      Number of Channels: 7
      Recorded Channels: ex, ey, hx, hy, hz, temperature, voltage
      Start: 2020-01-01T00:00:00+00:00
      End:   2021-01-01T12:00:00+00:00
      --------------------
      Run ID: mt01b
      Number of Channels: 7
      Recorded Channels: ex, ey, hx, hy, hz, temperature, voltage
      Start: 2020-01-01T00:00:00+00:00
      End:   2021-01-01T12:00:00+00:00
      --------------------

From an experiment you can access a channel knowing either the index or key word of the survey, station, and run. This is a mix of using index values and keys.

[8]:
ch_ex = experiment.surveys[0].stations["mt01"].runs[0].channels["ex"]
# set some values
ch_ex.dipole_length = 100
ch_ex.measurement_azimuth = 10
ch_ex.negative.x = -50
ch_ex.positive.x = 50
ch_ex.sample_rate = 256
ch_ex
[8]:
{
    "electric": {
        "channel_number": 0,
        "component": "ex",
        "data_quality.rating.value": 0,
        "dipole_length": 100.0,
        "filter.applied": [
            false
        ],
        "filter.name": [],
        "measurement_azimuth": 10.0,
        "measurement_tilt": 0.0,
        "negative.elevation": 0.0,
        "negative.id": null,
        "negative.latitude": 0.0,
        "negative.longitude": 0.0,
        "negative.manufacturer": null,
        "negative.type": null,
        "negative.x": -50.0,
        "positive.elevation": 0.0,
        "positive.id": null,
        "positive.latitude": 0.0,
        "positive.longitude": 0.0,
        "positive.manufacturer": null,
        "positive.type": null,
        "positive.x": 50.0,
        "sample_rate": 256.0,
        "time_period.end": "2021-01-01T12:00:00+00:00",
        "time_period.start": "2020-01-01T00:00:00+00:00",
        "type": "electric",
        "units": null
    }
}

The values are updated in the experiment object.

[9]:
experiment.surveys[0].stations["mt01"].runs[0].channels["ex"]
[9]:
{
    "electric": {
        "channel_number": 0,
        "component": "ex",
        "data_quality.rating.value": 0,
        "dipole_length": 100.0,
        "filter.applied": [
            false
        ],
        "filter.name": [],
        "measurement_azimuth": 10.0,
        "measurement_tilt": 0.0,
        "negative.elevation": 0.0,
        "negative.id": null,
        "negative.latitude": 0.0,
        "negative.longitude": 0.0,
        "negative.manufacturer": null,
        "negative.type": null,
        "negative.x": -50.0,
        "positive.elevation": 0.0,
        "positive.id": null,
        "positive.latitude": 0.0,
        "positive.longitude": 0.0,
        "positive.manufacturer": null,
        "positive.type": null,
        "positive.x": 50.0,
        "sample_rate": 256.0,
        "time_period.end": "2021-01-01T12:00:00+00:00",
        "time_period.start": "2020-01-01T00:00:00+00:00",
        "type": "electric",
        "units": null
    }
}

From Field Notes

Field notes are important but can be a pain to keep track of, whether they are written in notebooks, kept on tablets, or in various formats. Say you have a spreadsheet of field notes and now you’d like to make some metadata objects.

[10]:
#TODO
[ ]: