AURORA

Aurora is a Python library for processing natural source electromagnetic data. It uses MTH5 formatted Magnetotelluric data and a configuration file as inputs and generates transfer functions that can be formatted as EMTF XML or other output formats.

Documentation for the Aurora project can be found at http://simpeg.xyz/aurora/

Installing

We recommend installing Python (>= 3.6) using Anaconda or Miniconda

Conda forge

The simplest way to install aurora is using conda-forge:

conda install -c conda-forge aurora

Pypi

You can also use pypi to install aurora:

pip install aurora

From source

If you would like to install aurora from GitHub, you can clone it:

git clone https://github.com/simpeg/aurora.git

and install it:

cd aurora
pip install -e .

Issues

If you run into installation challenges, please post an issue on GitHub.

Build an MTH5 and Operate the Aurora Pipeline

This notebook pulls MT miniSEED data from the IRIS Dataselect web service and produces MTH5 out of it. It outlines the process of making an MTH5 file, generating a processing config, and running the Aurora processor.

It assumes that aurora, mth5, and mt_metadata have all been installed.

In this “new” version, the workflow has changed somewhat.

  1. The process_mth5 call works with a dataset dataframe, rather than a single run_id

  2. The config object is now based on the mt_metadata.base Base class

  3. Remote reference processing is supported (at least in theory)

Flow of this notebook

Section 1: Here we do imports and construct a table of the data that we will access to build the mth5. Note that there is no explanation here as to the table source – a future update can show how to create such a table from IRIS data_availability tools

Seciton 2: the metadata and the data are accessed, and the mth5 is created and stored.

Section 3:

[1]:
# Required imports for the program.
from pathlib import Path
import pandas as pd
from mth5.clients.make_mth5 import MakeMTH5
from mth5 import mth5, timeseries
from mt_metadata.utils.mttime import get_now_utc, MTime
from aurora.config import BANDS_DEFAULT_FILE
from aurora.config.config_creator import ConfigCreator
from aurora.pipelines.process_mth5 import process_mth5
from aurora.tf_kernel.dataset import DatasetDefinition
from aurora.tf_kernel.helpers import extract_run_summary_from_mth5
2022-06-03 17:47:11,454 [line 135] mth5.setup_logger - INFO: Logging file can be found /home/kkappler/software/irismt/mth5/logs/mth5_debug.log

Build an MTH5 file from information extracted by IRIS

[2]:
# Set path so MTH5 file builds to current working directory.
default_path = Path().cwd()
default_path
[2]:
PosixPath('/home/kkappler/software/irismt/aurora/docs/notebooks')
[3]:
# Initialize the Make MTH5 code.
m = MakeMTH5(mth5_version='0.1.0')
m.client = "IRIS"

Specify the data to access from IRIS

Note that here we explicitly prescribe the data, but this dataframe could be built from IRIS data availability tools in a programatic way

[4]:
# Generate data frame of FDSN Network, Station, Location, Channel, Startime, Endtime codes of interest

CAS04LQE = ['8P', 'CAS04', '', 'LQE', '2020-06-02T19:00:00', '2020-07-13T19:00:00']
CAS04LQN = ['8P', 'CAS04', '', 'LQN', '2020-06-02T19:00:00', '2020-07-13T19:00:00']
CAS04BFE = ['8P', 'CAS04', '', 'LFE', '2020-06-02T19:00:00', '2020-07-13T19:00:00']
CAS04BFN = ['8P', 'CAS04', '', 'LFN', '2020-06-02T19:00:00', '2020-07-13T19:00:00']
CAS04BFZ = ['8P', 'CAS04', '', 'LFZ', '2020-06-02T19:00:00', '2020-07-13T19:00:00']

request_list = [CAS04LQE, CAS04LQN, CAS04BFE, CAS04BFN, CAS04BFZ]

# Turn list into dataframe
request_df =  pd.DataFrame(request_list, columns=m.column_names)
[5]:
# Inspect the dataframe
print(request_df)
  network station location channel                start                  end
0      8P   CAS04              LQE  2020-06-02T19:00:00  2020-07-13T19:00:00
1      8P   CAS04              LQN  2020-06-02T19:00:00  2020-07-13T19:00:00
2      8P   CAS04              LFE  2020-06-02T19:00:00  2020-07-13T19:00:00
3      8P   CAS04              LFN  2020-06-02T19:00:00  2020-07-13T19:00:00
4      8P   CAS04              LFZ  2020-06-02T19:00:00  2020-07-13T19:00:00
[6]:
# Request the inventory information from IRIS
inventory = m.get_inventory_from_df(request_df, data=False)
[7]:
# Inspect the inventory
inventory
[7]:
(Inventory created at 2022-06-04T00:47:20.278242Z
        Created by: ObsPy 1.2.2
                    https://www.obspy.org
        Sending institution: MTH5
        Contains:
                Networks (1):
                        8P
                Stations (1):
                        8P.CAS04 (Corral Hollow, CA, USA)
                Channels (5):
                        8P.CAS04..LFZ, 8P.CAS04..LFN, 8P.CAS04..LFE, 8P.CAS04..LQN,
                        8P.CAS04..LQE,
 0 Trace(s) in Stream:
)

Builds an MTH5 file from the user defined database. Note: Intact keeps the MTH5 open after it is done building

With the mth5 object set, we are ready to actually request the data from the fdsn client (IRIS) and save it to an MTH5 file. This process builds an MTH5 file and can take some time depending on how much data is requested.

Note: interact keeps the MTH5 open after it is done building

[8]:
interact = True
mth5_object = m.make_mth5_from_fdsnclient(request_df, interact=interact)
2022-06-03 17:47:31,516 [line 591] mth5.mth5.MTH5.open_mth5 - WARNING: 8P_CAS04.h5 will be overwritten in 'w' mode
2022-06-03 17:47:31,939 [line 656] mth5.mth5.MTH5._initialize_file - INFO: Initialized MTH5 0.1.0 file /home/kkappler/software/irismt/aurora/docs/notebooks/8P_CAS04.h5 in mode w
2022-06-03 17:48:28,522 [line 121] mt_metadata.base.metadata.station.add_run - WARNING: Run a is being overwritten with current information
2022-06-03T17:48:28 [line 136] obspy_stages.create_filter_from_stage - INFO: Converting PoleZerosResponseStage electric_si_units to a CoefficientFilter
2022-06-03T17:48:28 [line 136] obspy_stages.create_filter_from_stage - INFO: Converting PoleZerosResponseStage electric_dipole_92.000 to a CoefficientFilter
2022-06-03T17:48:28 [line 136] obspy_stages.create_filter_from_stage - INFO: Converting PoleZerosResponseStage electric_si_units to a CoefficientFilter
2022-06-03T17:48:28 [line 136] obspy_stages.create_filter_from_stage - INFO: Converting PoleZerosResponseStage electric_dipole_92.000 to a CoefficientFilter
More or less runs have been requested by the user than are defined in the metadata. Runs will be defined but only the requested run extents contain time series data based on the users request.
2022-06-03 17:48:31,009 [line 224] mth5.timeseries.run_ts.RunTS.validate_metadata - WARNING: start time of dataset 2020-06-02T19:00:00+00:00 does not match metadata start 2020-06-02T18:41:43+00:00 updating metatdata value to 2020-06-02T19:00:00+00:00
2022-06-03 17:48:51,497 [line 462] mth5.timeseries.run_ts.RunTS.from_obspy_stream - WARNING: could not find ey
2022-06-03 17:49:04,164 [line 462] mth5.timeseries.run_ts.RunTS.from_obspy_stream - WARNING: could not find ex
2022-06-03 17:49:04,272 [line 462] mth5.timeseries.run_ts.RunTS.from_obspy_stream - WARNING: could not find ey
2022-06-03 17:49:04,770 [line 235] mth5.timeseries.run_ts.RunTS.validate_metadata - WARNING: end time of dataset 2020-07-13T19:00:00+00:00 does not match metadata end 2020-07-13T21:46:12+00:00 updating metatdata value to 2020-07-13T19:00:00+00:00

Examine and Update the MTH5 object

With the open MTH5 Object, we can start to examine what is in it. For example, we retrieve the filename and file_version. You can additionally do things such as getting the station information and edit it by setting a new value, in this case the declination model.

[9]:
mth5_object
[9]:
/:
====================
    |- Group: Survey
    ----------------
        |- Group: Filters
        -----------------
            |- Group: coefficient
            ---------------------
                |- Group: electric_analog_to_digital
                ------------------------------------
                |- Group: electric_dipole_92.000
                --------------------------------
                |- Group: electric_si_units
                ---------------------------
                |- Group: magnetic_analog_to_digital
                ------------------------------------
            |- Group: fap
            -------------
            |- Group: fir
            -------------
            |- Group: time_delay
            --------------------
                |- Group: electric_time_offset
                ------------------------------
                |- Group: hx_time_offset
                ------------------------
                |- Group: hy_time_offset
                ------------------------
                |- Group: hz_time_offset
                ------------------------
            |- Group: zpk
            -------------
                |- Group: electric_butterworth_high_pass
                ----------------------------------------
                    --> Dataset: poles
                    ....................
                    --> Dataset: zeros
                    ....................
                |- Group: electric_butterworth_low_pass
                ---------------------------------------
                    --> Dataset: poles
                    ....................
                    --> Dataset: zeros
                    ....................
                |- Group: magnetic_butterworth_low_pass
                ---------------------------------------
                    --> Dataset: poles
                    ....................
                    --> Dataset: zeros
                    ....................
        |- Group: Reports
        -----------------
        |- Group: Standards
        -------------------
            --> Dataset: summary
            ......................
        |- Group: Stations
        ------------------
            |- Group: CAS04
            ---------------
                |- Group: Transfer_Functions
                ----------------------------
                |- Group: a
                -----------
                    --> Dataset: ex
                    .................
                    --> Dataset: ey
                    .................
                    --> Dataset: hx
                    .................
                    --> Dataset: hy
                    .................
                    --> Dataset: hz
                    .................
                |- Group: b
                -----------
                    --> Dataset: ex
                    .................
                    --> Dataset: ey
                    .................
                    --> Dataset: hx
                    .................
                    --> Dataset: hy
                    .................
                    --> Dataset: hz
                    .................
                |- Group: c
                -----------
                    --> Dataset: ex
                    .................
                    --> Dataset: ey
                    .................
                    --> Dataset: hx
                    .................
                    --> Dataset: hy
                    .................
                    --> Dataset: hz
                    .................
                |- Group: d
                -----------
                    --> Dataset: ex
                    .................
                    --> Dataset: ey
                    .................
                    --> Dataset: hx
                    .................
                    --> Dataset: hy
                    .................
                    --> Dataset: hz
                    .................
        --> Dataset: channel_summary
        ..............................
        --> Dataset: tf_summary
        .........................

Need documentation:

Is the cell below required? Or is it an example of some metadata specification?

[10]:
# Edit and update the MTH5 metadata
s = mth5_object.get_station("CAS04")
print(s.metadata.location.declination.model)
s.metadata.location.declination.model = 'IGRF'
print(s.metadata.location.declination.model)
s.write_metadata()    # writes to file mth5_filename
IGRF-13
IGRF
[11]:
# Collect information from the MTh5 Object and use it in the config files.
mth5_filename = mth5_object.filename
version = mth5_object.file_version
print(mth5_filename)
/home/kkappler/software/irismt/aurora/docs/notebooks/8P_CAS04.h5
[12]:
# Get the available stations and runs from the MTH5 object
mth5_object.channel_summary.summarize()
ch_summary = mth5_object.channel_summary.to_dataframe()
ch_summary
[12]:
survey station run latitude longitude elevation component start end n_samples sample_rate measurement_type azimuth tilt units hdf5_reference run_hdf5_reference station_hdf5_reference
0 CONUS South CAS04 a 37.633351 -121.468382 329.3875 ex 2020-06-02 19:00:00+00:00 2020-06-02 22:07:46+00:00 11267 1.0 electric 13.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
1 CONUS South CAS04 a 37.633351 -121.468382 329.3875 ey 2020-06-02 19:00:00+00:00 2020-06-02 22:07:46+00:00 11267 1.0 electric 103.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
2 CONUS South CAS04 a 37.633351 -121.468382 329.3875 hx 2020-06-02 19:00:00+00:00 2020-06-02 22:07:46+00:00 11267 1.0 magnetic 13.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
3 CONUS South CAS04 a 37.633351 -121.468382 329.3875 hy 2020-06-02 19:00:00+00:00 2020-06-02 22:07:46+00:00 11267 1.0 magnetic 103.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
4 CONUS South CAS04 a 37.633351 -121.468382 329.3875 hz 2020-06-02 19:00:00+00:00 2020-06-02 22:07:46+00:00 11267 1.0 magnetic 0.0 90.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
5 CONUS South CAS04 b 37.633351 -121.468382 329.3875 ex 2020-06-02 22:24:55+00:00 2020-06-12 17:52:23+00:00 847649 1.0 electric 13.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
6 CONUS South CAS04 b 37.633351 -121.468382 329.3875 ey 2020-06-02 22:24:55+00:00 2020-06-12 17:52:23+00:00 847649 1.0 electric 103.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
7 CONUS South CAS04 b 37.633351 -121.468382 329.3875 hx 2020-06-02 22:24:55+00:00 2020-06-12 17:52:23+00:00 847649 1.0 magnetic 13.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
8 CONUS South CAS04 b 37.633351 -121.468382 329.3875 hy 2020-06-02 22:24:55+00:00 2020-06-12 17:52:23+00:00 847649 1.0 magnetic 103.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
9 CONUS South CAS04 b 37.633351 -121.468382 329.3875 hz 2020-06-02 22:24:55+00:00 2020-06-12 17:52:23+00:00 847649 1.0 magnetic 0.0 90.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
10 CONUS South CAS04 c 37.633351 -121.468382 329.3875 ex 2020-06-12 18:32:17+00:00 2020-07-01 17:32:59+00:00 1638043 1.0 electric 13.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
11 CONUS South CAS04 c 37.633351 -121.468382 329.3875 ey 2020-06-12 18:32:17+00:00 2020-07-01 17:32:59+00:00 1638043 1.0 electric 0.0 0.0 counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
12 CONUS South CAS04 c 37.633351 -121.468382 329.3875 hx 2020-06-12 18:32:17+00:00 2020-07-01 17:32:59+00:00 1638043 1.0 magnetic 13.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
13 CONUS South CAS04 c 37.633351 -121.468382 329.3875 hy 2020-06-12 18:32:17+00:00 2020-07-01 17:32:59+00:00 1638043 1.0 magnetic 103.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
14 CONUS South CAS04 c 37.633351 -121.468382 329.3875 hz 2020-06-12 18:32:17+00:00 2020-07-01 17:32:59+00:00 1638043 1.0 magnetic 0.0 90.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
15 CONUS South CAS04 d 37.633351 -121.468382 329.3875 ex 2020-07-01 19:36:55+00:00 2020-07-13 19:00:00+00:00 1034586 1.0 electric 0.0 0.0 counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
16 CONUS South CAS04 d 37.633351 -121.468382 329.3875 ey 2020-07-01 19:36:55+00:00 2020-07-13 19:00:00+00:00 1034586 1.0 electric 0.0 0.0 counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
17 CONUS South CAS04 d 37.633351 -121.468382 329.3875 hx 2020-07-01 19:36:55+00:00 2020-07-13 19:00:00+00:00 1034586 1.0 magnetic 13.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
18 CONUS South CAS04 d 37.633351 -121.468382 329.3875 hy 2020-07-01 19:36:55+00:00 2020-07-13 19:00:00+00:00 1034586 1.0 magnetic 103.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
19 CONUS South CAS04 d 37.633351 -121.468382 329.3875 hz 2020-07-01 19:36:55+00:00 2020-07-13 19:00:00+00:00 1034586 1.0 magnetic 0.0 90.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>

If MTH5 file already exists you can start here

If you dont want to execute the previous code to get data again

[4]:
#interact = False
if interact:
    pass
else:
    h5_path = default_path.joinpath("8P_CAS04.h5")
    mth5_object = mth5.MTH5(file_version="0.1.0")
    #mth5_object.open_mth5(config.stations.local.mth5_path, mode="a")
    mth5_object.open_mth5(h5_path, mode="a")
    ch_summary = mth5_object.channel_summary.to_dataframe()


Generate an Aurora Configuration file using MTH5 as an input

Up to this point, we have used mth5 and mt_metadata, but haven’t yet used aurora. So we will use the MTH5 that we just created (and examined and updated) as input into Aurora.

First, we get a list of the available runs to process from the MTH5

[57]:
ch_summary
[57]:
survey station run latitude longitude elevation component start end n_samples sample_rate measurement_type azimuth tilt units hdf5_reference run_hdf5_reference station_hdf5_reference
0 CONUS South CAS04 a 37.633351 -121.468382 329.3875 ex 2020-06-02 19:00:00+00:00 2020-06-02 22:07:46+00:00 11267 1.0 electric 13.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
1 CONUS South CAS04 a 37.633351 -121.468382 329.3875 ey 2020-06-02 19:00:00+00:00 2020-06-02 22:07:46+00:00 11267 1.0 electric 103.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
2 CONUS South CAS04 a 37.633351 -121.468382 329.3875 hx 2020-06-02 19:00:00+00:00 2020-06-02 22:07:46+00:00 11267 1.0 magnetic 13.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
3 CONUS South CAS04 a 37.633351 -121.468382 329.3875 hy 2020-06-02 19:00:00+00:00 2020-06-02 22:07:46+00:00 11267 1.0 magnetic 103.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
4 CONUS South CAS04 a 37.633351 -121.468382 329.3875 hz 2020-06-02 19:00:00+00:00 2020-06-02 22:07:46+00:00 11267 1.0 magnetic 0.0 90.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
5 CONUS South CAS04 b 37.633351 -121.468382 329.3875 ex 2020-06-02 22:24:55+00:00 2020-06-12 17:52:23+00:00 847649 1.0 electric 13.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
6 CONUS South CAS04 b 37.633351 -121.468382 329.3875 ey 2020-06-02 22:24:55+00:00 2020-06-12 17:52:23+00:00 847649 1.0 electric 103.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
7 CONUS South CAS04 b 37.633351 -121.468382 329.3875 hx 2020-06-02 22:24:55+00:00 2020-06-12 17:52:23+00:00 847649 1.0 magnetic 13.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
8 CONUS South CAS04 b 37.633351 -121.468382 329.3875 hy 2020-06-02 22:24:55+00:00 2020-06-12 17:52:23+00:00 847649 1.0 magnetic 103.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
9 CONUS South CAS04 b 37.633351 -121.468382 329.3875 hz 2020-06-02 22:24:55+00:00 2020-06-12 17:52:23+00:00 847649 1.0 magnetic 0.0 90.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
10 CONUS South CAS04 c 37.633351 -121.468382 329.3875 ex 2020-06-12 18:32:17+00:00 2020-07-01 17:32:59+00:00 1638043 1.0 electric 13.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
11 CONUS South CAS04 c 37.633351 -121.468382 329.3875 ey 2020-06-12 18:32:17+00:00 2020-07-01 17:32:59+00:00 1638043 1.0 electric 0.0 0.0 counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
12 CONUS South CAS04 c 37.633351 -121.468382 329.3875 hx 2020-06-12 18:32:17+00:00 2020-07-01 17:32:59+00:00 1638043 1.0 magnetic 13.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
13 CONUS South CAS04 c 37.633351 -121.468382 329.3875 hy 2020-06-12 18:32:17+00:00 2020-07-01 17:32:59+00:00 1638043 1.0 magnetic 103.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
14 CONUS South CAS04 c 37.633351 -121.468382 329.3875 hz 2020-06-12 18:32:17+00:00 2020-07-01 17:32:59+00:00 1638043 1.0 magnetic 0.0 90.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
15 CONUS South CAS04 d 37.633351 -121.468382 329.3875 ex 2020-07-01 19:36:55+00:00 2020-07-13 19:00:00+00:00 1034586 1.0 electric 0.0 0.0 counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
16 CONUS South CAS04 d 37.633351 -121.468382 329.3875 ey 2020-07-01 19:36:55+00:00 2020-07-13 19:00:00+00:00 1034586 1.0 electric 0.0 0.0 counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
17 CONUS South CAS04 d 37.633351 -121.468382 329.3875 hx 2020-07-01 19:36:55+00:00 2020-07-13 19:00:00+00:00 1034586 1.0 magnetic 13.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
18 CONUS South CAS04 d 37.633351 -121.468382 329.3875 hy 2020-07-01 19:36:55+00:00 2020-07-13 19:00:00+00:00 1034586 1.0 magnetic 103.2 0.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
19 CONUS South CAS04 d 37.633351 -121.468382 329.3875 hz 2020-07-01 19:36:55+00:00 2020-07-13 19:00:00+00:00 1034586 1.0 magnetic 0.0 90.0 digital counts <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
[17]:
available_runs = ch_summary.run.unique()
sr = ch_summary.sample_rate.unique()
if len(sr) != 1:
    print('Only one sample rate per run is available')
available_stations = ch_summary.station.unique()
[7]:
mth5_object.filename

[7]:
PosixPath('/home/kkappler/software/irismt/aurora/docs/notebooks/8P_CAS04.h5')
[ ]:
available_stations[0]

Now, we condense the channel summary into a run_summary.

This method takes an iterable of mth5_objs or h5_paths

If the mth5 file is closed, you can get the run summary this way

[15]:
from aurora.tf_kernel.helpers import extract_run_summaries_from_mth5s
h5_path = default_path.joinpath("8P_CAS04.h5")
run_summary = extract_run_summaries_from_mth5s([h5_path,])
2022-06-03 17:53:53,098 [line 731] mth5.mth5.MTH5.close_mth5 - INFO: Flushing and closing /home/kkappler/software/irismt/aurora/docs/notebooks/8P_CAS04.h5

Otherwise, work from the mth5_object

[16]:
run_summary = extract_run_summary_from_mth5(mth5_object)

[17]:
print(run_summary.columns)
Index(['station_id', 'run_id', 'start', 'end', 'sample_rate', 'input_channels',
       'output_channels', 'channel_scale_factors', 'mth5_path'],
      dtype='object')
[18]:
print(run_summary[['station_id', 'run_id', 'start', 'end', ]])
  station_id run_id                     start                       end
0      CAS04      a 2020-06-02 19:00:00+00:00 2020-06-02 22:07:46+00:00
1      CAS04      b 2020-06-02 22:24:55+00:00 2020-06-12 17:52:23+00:00
2      CAS04      c 2020-06-12 18:32:17+00:00 2020-07-01 17:32:59+00:00
3      CAS04      d 2020-07-01 19:36:55+00:00 2020-07-13 19:00:00+00:00

There are no reference stations, set all rows to False

[19]:
run_summary["remote"] = False

Make an aurora configuration file (and then save that json file.)

[20]:
    cc = ConfigCreator()#config_path=CONFIG_PATH)
    config = cc.create_run_processing_object(emtf_band_file=BANDS_DEFAULT_FILE,
                                        sample_rate=sr[0]
                                        )
    config.stations.from_dataset_dataframe(run_summary)
    for decimation in config.decimations:
        decimation.estimator.engine = "RME"

Take a look at the config:

[21]:
config
[21]:
{
    "processing": {
        "decimations": [
            {
                "decimation_level": {
                    "anti_alias_filter": "default",
                    "bands": [
                        {
                            "band": {
                                "decimation_level": 0,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 30,
                                "index_min": 25
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 0,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 24,
                                "index_min": 20
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 0,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 19,
                                "index_min": 16
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 0,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 15,
                                "index_min": 13
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 0,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 12,
                                "index_min": 10
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 0,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 9,
                                "index_min": 8
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 0,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 7,
                                "index_min": 6
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 0,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 5,
                                "index_min": 5
                            }
                        }
                    ],
                    "decimation.factor": 1.0,
                    "decimation.level": 0,
                    "decimation.method": "default",
                    "decimation.sample_rate": 1.0,
                    "estimator.engine": "RME",
                    "estimator.estimate_per_channel": true,
                    "extra_pre_fft_detrend_type": "linear",
                    "input_channels": [
                        "hx",
                        "hy"
                    ],
                    "output_channels": [
                        "hz",
                        "ex",
                        "ey"
                    ],
                    "prewhitening_type": "first difference",
                    "reference_channels": [
                        "hx",
                        "hy"
                    ],
                    "regression.max_iterations": 10,
                    "regression.max_redescending_iterations": 2,
                    "regression.minimum_cycles": 10,
                    "window.num_samples": 128,
                    "window.overlap": 32,
                    "window.type": "boxcar"
                }
            },
            {
                "decimation_level": {
                    "anti_alias_filter": "default",
                    "bands": [
                        {
                            "band": {
                                "decimation_level": 1,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 17,
                                "index_min": 14
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 1,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 13,
                                "index_min": 11
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 1,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 10,
                                "index_min": 9
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 1,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 8,
                                "index_min": 7
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 1,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 6,
                                "index_min": 6
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 1,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 5,
                                "index_min": 5
                            }
                        }
                    ],
                    "decimation.factor": 4.0,
                    "decimation.level": 1,
                    "decimation.method": "default",
                    "decimation.sample_rate": 0.25,
                    "estimator.engine": "RME",
                    "estimator.estimate_per_channel": true,
                    "extra_pre_fft_detrend_type": "linear",
                    "input_channels": [
                        "hx",
                        "hy"
                    ],
                    "output_channels": [
                        "hz",
                        "ex",
                        "ey"
                    ],
                    "prewhitening_type": "first difference",
                    "reference_channels": [
                        "hx",
                        "hy"
                    ],
                    "regression.max_iterations": 10,
                    "regression.max_redescending_iterations": 2,
                    "regression.minimum_cycles": 10,
                    "window.num_samples": 128,
                    "window.overlap": 32,
                    "window.type": "boxcar"
                }
            },
            {
                "decimation_level": {
                    "anti_alias_filter": "default",
                    "bands": [
                        {
                            "band": {
                                "decimation_level": 2,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 17,
                                "index_min": 14
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 2,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 13,
                                "index_min": 11
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 2,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 10,
                                "index_min": 9
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 2,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 8,
                                "index_min": 7
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 2,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 6,
                                "index_min": 6
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 2,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 5,
                                "index_min": 5
                            }
                        }
                    ],
                    "decimation.factor": 4.0,
                    "decimation.level": 2,
                    "decimation.method": "default",
                    "decimation.sample_rate": 0.0625,
                    "estimator.engine": "RME",
                    "estimator.estimate_per_channel": true,
                    "extra_pre_fft_detrend_type": "linear",
                    "input_channels": [
                        "hx",
                        "hy"
                    ],
                    "output_channels": [
                        "hz",
                        "ex",
                        "ey"
                    ],
                    "prewhitening_type": "first difference",
                    "reference_channels": [
                        "hx",
                        "hy"
                    ],
                    "regression.max_iterations": 10,
                    "regression.max_redescending_iterations": 2,
                    "regression.minimum_cycles": 10,
                    "window.num_samples": 128,
                    "window.overlap": 32,
                    "window.type": "boxcar"
                }
            },
            {
                "decimation_level": {
                    "anti_alias_filter": "default",
                    "bands": [
                        {
                            "band": {
                                "decimation_level": 3,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 22,
                                "index_min": 18
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 3,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 17,
                                "index_min": 14
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 3,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 13,
                                "index_min": 10
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 3,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 9,
                                "index_min": 7
                            }
                        },
                        {
                            "band": {
                                "decimation_level": 3,
                                "frequency_max": 0,
                                "frequency_min": 0,
                                "index_max": 6,
                                "index_min": 5
                            }
                        }
                    ],
                    "decimation.factor": 4.0,
                    "decimation.level": 3,
                    "decimation.method": "default",
                    "decimation.sample_rate": 0.015625,
                    "estimator.engine": "RME",
                    "estimator.estimate_per_channel": true,
                    "extra_pre_fft_detrend_type": "linear",
                    "input_channels": [
                        "hx",
                        "hy"
                    ],
                    "output_channels": [
                        "hz",
                        "ex",
                        "ey"
                    ],
                    "prewhitening_type": "first difference",
                    "reference_channels": [
                        "hx",
                        "hy"
                    ],
                    "regression.max_iterations": 10,
                    "regression.max_redescending_iterations": 2,
                    "regression.minimum_cycles": 10,
                    "window.num_samples": 128,
                    "window.overlap": 32,
                    "window.type": "boxcar"
                }
            }
        ],
        "id": "None-None",
        "stations.local.id": "CAS04",
        "stations.local.mth5_path": "/home/kkappler/software/irismt/aurora/docs/notebooks/8P_CAS04.h5",
        "stations.local.remote": false,
        "stations.local.runs": [
            {
                "run": {
                    "id": "a",
                    "input_channels": [
                        {
                            "channel": {
                                "id": "hx",
                                "scale_factor": 1.0
                            }
                        },
                        {
                            "channel": {
                                "id": "hy",
                                "scale_factor": 1.0
                            }
                        }
                    ],
                    "output_channels": [
                        {
                            "channel": {
                                "id": "ex",
                                "scale_factor": 1.0
                            }
                        },
                        {
                            "channel": {
                                "id": "ey",
                                "scale_factor": 1.0
                            }
                        },
                        {
                            "channel": {
                                "id": "hz",
                                "scale_factor": 1.0
                            }
                        }
                    ],
                    "sample_rate": 1.0,
                    "time_periods": [
                        {
                            "time_period": {
                                "end": "2020-06-02T22:07:46+00:00",
                                "start": "2020-06-02T19:00:00+00:00"
                            }
                        }
                    ]
                }
            },
            {
                "run": {
                    "id": "b",
                    "input_channels": [
                        {
                            "channel": {
                                "id": "hx",
                                "scale_factor": 1.0
                            }
                        },
                        {
                            "channel": {
                                "id": "hy",
                                "scale_factor": 1.0
                            }
                        }
                    ],
                    "output_channels": [
                        {
                            "channel": {
                                "id": "ex",
                                "scale_factor": 1.0
                            }
                        },
                        {
                            "channel": {
                                "id": "ey",
                                "scale_factor": 1.0
                            }
                        },
                        {
                            "channel": {
                                "id": "hz",
                                "scale_factor": 1.0
                            }
                        }
                    ],
                    "sample_rate": 1.0,
                    "time_periods": [
                        {
                            "time_period": {
                                "end": "2020-06-12T17:52:23+00:00",
                                "start": "2020-06-02T22:24:55+00:00"
                            }
                        }
                    ]
                }
            },
            {
                "run": {
                    "id": "c",
                    "input_channels": [
                        {
                            "channel": {
                                "id": "hx",
                                "scale_factor": 1.0
                            }
                        },
                        {
                            "channel": {
                                "id": "hy",
                                "scale_factor": 1.0
                            }
                        }
                    ],
                    "output_channels": [
                        {
                            "channel": {
                                "id": "ex",
                                "scale_factor": 1.0
                            }
                        },
                        {
                            "channel": {
                                "id": "ey",
                                "scale_factor": 1.0
                            }
                        },
                        {
                            "channel": {
                                "id": "hz",
                                "scale_factor": 1.0
                            }
                        }
                    ],
                    "sample_rate": 1.0,
                    "time_periods": [
                        {
                            "time_period": {
                                "end": "2020-07-01T17:32:59+00:00",
                                "start": "2020-06-12T18:32:17+00:00"
                            }
                        }
                    ]
                }
            },
            {
                "run": {
                    "id": "d",
                    "input_channels": [
                        {
                            "channel": {
                                "id": "hx",
                                "scale_factor": 1.0
                            }
                        },
                        {
                            "channel": {
                                "id": "hy",
                                "scale_factor": 1.0
                            }
                        }
                    ],
                    "output_channels": [
                        {
                            "channel": {
                                "id": "ex",
                                "scale_factor": 1.0
                            }
                        },
                        {
                            "channel": {
                                "id": "ey",
                                "scale_factor": 1.0
                            }
                        },
                        {
                            "channel": {
                                "id": "hz",
                                "scale_factor": 1.0
                            }
                        }
                    ],
                    "sample_rate": 1.0,
                    "time_periods": [
                        {
                            "time_period": {
                                "end": "2020-07-13T19:00:00+00:00",
                                "start": "2020-07-01T19:36:55+00:00"
                            }
                        }
                    ]
                }
            }
        ],
        "stations.remote": []
    }
}

Run the Aurora Pipeline using the input MTh5 and Confiugration File

[22]:
dataset_definition = DatasetDefinition()
dataset_definition.df = run_summary
dataset_definition.df
[22]:
station_id run_id start end sample_rate input_channels output_channels channel_scale_factors mth5_path remote
0 CAS04 a 2020-06-02 19:00:00+00:00 2020-06-02 22:07:46+00:00 1.0 [hx, hy] [ex, ey, hz] {'ex': 1.0, 'ey': 1.0, 'hx': 1.0, 'hy': 1.0, '... /home/kkappler/software/irismt/aurora/docs/not... False
1 CAS04 b 2020-06-02 22:24:55+00:00 2020-06-12 17:52:23+00:00 1.0 [hx, hy] [ex, ey, hz] {'ex': 1.0, 'ey': 1.0, 'hx': 1.0, 'hy': 1.0, '... /home/kkappler/software/irismt/aurora/docs/not... False
2 CAS04 c 2020-06-12 18:32:17+00:00 2020-07-01 17:32:59+00:00 1.0 [hx, hy] [ex, ey, hz] {'ex': 1.0, 'ey': 1.0, 'hx': 1.0, 'hy': 1.0, '... /home/kkappler/software/irismt/aurora/docs/not... False
3 CAS04 d 2020-07-01 19:36:55+00:00 2020-07-13 19:00:00+00:00 1.0 [hx, hy] [ex, ey, hz] {'ex': 1.0, 'ey': 1.0, 'hx': 1.0, 'hy': 1.0, '... /home/kkappler/software/irismt/aurora/docs/not... False

Select the runs you want to process

use the run_list variable

[23]:
run_list = ['b',]
new_df = dataset_definition.restrict_runs_by_station("CAS04", run_list, overwrite=True)
print(new_df)
dataset_definition.df
   index station_id run_id                     start  \
0      1      CAS04      b 2020-06-02 22:24:55+00:00

                        end  sample_rate input_channels output_channels  \
0 2020-06-12 17:52:23+00:00          1.0       [hx, hy]    [ex, ey, hz]

                               channel_scale_factors  \
0  {'ex': 1.0, 'ey': 1.0, 'hx': 1.0, 'hy': 1.0, '...

                                           mth5_path  remote
0  /home/kkappler/software/irismt/aurora/docs/not...   False
[23]:
index station_id run_id start end sample_rate input_channels output_channels channel_scale_factors mth5_path remote
0 1 CAS04 b 2020-06-02 22:24:55+00:00 2020-06-12 17:52:23+00:00 1.0 [hx, hy] [ex, ey, hz] {'ex': 1.0, 'ey': 1.0, 'hx': 1.0, 'hy': 1.0, '... /home/kkappler/software/irismt/aurora/docs/not... False
[24]:
show_plot = True
tf_cls = process_mth5(config,
                    dataset_definition,
                    units="MT",
                    show_plot=show_plot,
                    z_file_path=None,
                    return_collection=False
                )
Processing config indicates 4 decimation levels
fix this so that it gets from config based on station_id, without caring if local or remote
/home/kkappler/software/irismt/aurora/aurora/pipelines/time_series_helpers.py:224: RuntimeWarning: invalid value encountered in true_divide
  stft_obj[channel_id].data /= calibration_response
Processing band 25.728968s
Processing band 19.929573s
Processing band 15.164131s
Processing band 11.746086s
Processing band 9.195791s
Processing band 7.362526s
Processing band 5.856115s
Processing band 4.682492s
GET PLOTTER FROM MTpy
OK, now ser linewidth and markersize
_images/notebooks_operate_aurora_45_3.png
/home/kkappler/anaconda2/envs/py37/lib/python3.7/site-packages/pandas/core/indexing.py:1732: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  self._setitem_single_block(indexer, value, name)
fix this so that it gets from config based on station_id, without caring if local or remote
/home/kkappler/software/irismt/aurora/aurora/pipelines/time_series_helpers.py:224: RuntimeWarning: invalid value encountered in true_divide
  stft_obj[channel_id].data /= calibration_response
Processing band 102.915872s
Processing band 85.631182s
Processing band 68.881694s
Processing band 54.195827s
Processing band 43.003958s
Processing band 33.310722s
GET PLOTTER FROM MTpy
OK, now ser linewidth and markersize
_images/notebooks_operate_aurora_45_8.png
/home/kkappler/anaconda2/envs/py37/lib/python3.7/site-packages/pandas/core/indexing.py:1732: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  self._setitem_single_block(indexer, value, name)
fix this so that it gets from config based on station_id, without caring if local or remote
/home/kkappler/software/irismt/aurora/aurora/pipelines/time_series_helpers.py:224: RuntimeWarning: invalid value encountered in true_divide
  stft_obj[channel_id].data /= calibration_response
Processing band 411.663489s
Processing band 342.524727s
Processing band 275.526776s
Processing band 216.783308s
Processing band 172.015831s
Processing band 133.242890s
GET PLOTTER FROM MTpy
OK, now ser linewidth and markersize
_images/notebooks_operate_aurora_45_13.png
/home/kkappler/anaconda2/envs/py37/lib/python3.7/site-packages/pandas/core/indexing.py:1732: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  self._setitem_single_block(indexer, value, name)
fix this so that it gets from config based on station_id, without caring if local or remote
/home/kkappler/software/irismt/aurora/aurora/pipelines/time_series_helpers.py:224: RuntimeWarning: invalid value encountered in true_divide
  stft_obj[channel_id].data /= calibration_response
Processing band 1514.701336s
Processing band 1042.488956s
Processing band 723.371271s
Processing band 532.971560s
Processing band 412.837995s
GET PLOTTER FROM MTpy
OK, now ser linewidth and markersize
_images/notebooks_operate_aurora_45_18.png
2022-06-03 17:55:09,287 [line 731] mth5.mth5.MTH5.close_mth5 - INFO: Flushing and closing /home/kkappler/software/irismt/aurora/docs/notebooks/8P_CAS04.h5
['b']
[25]:
dataset_definition.df
2022-06-03 17:58:34,548 [line 113] mth5.groups.base.Run.__str__ - WARNING: MTH5 file is closed and cannot be accessed.
2022-06-03 17:58:34,830 [line 113] mth5.groups.base.Run.__str__ - WARNING: MTH5 file is closed and cannot be accessed.
[25]:
index station_id run_id start end sample_rate input_channels output_channels channel_scale_factors mth5_path remote mth5_obj run run_dataarray stft
0 1 CAS04 b 2020-06-02 22:24:55+00:00 2020-06-12 17:52:23+00:00 1.0 [hx, hy] [ex, ey, hz] {'ex': 1.0, 'ey': 1.0, 'hx': 1.0, 'hy': 1.0, '... /home/kkappler/software/irismt/aurora/docs/not... False HDF5 file is closed and cannot be accessed. MTH5 file is closed and cannot be accessed. [[<xarray.DataArray ()>\narray(-7814.971096500... None
[26]:

type(tf_cls)
[26]:
mt_metadata.transfer_functions.core.TF

Write the transfer functions generated by the Aurora pipeline

[27]:
 tf_cls.write_tf_file(fn="emtfxml_test.xml", file_type="emtfxml")
2022-06-03 17:58:38,607 [line 197] mt_metadata.transfer_functions.io.readwrite.write_file - INFO: Wrote emtfxml_test.xml
[27]:
EMTFXML(station='CAS04', latitude=37.63, longitude=-121.47, elevation=329.39)
[28]:
tf_cls.write_tf_file(fn="emtfxml_test.xml", file_type="edi")
2022-06-03 17:58:39,327 [line 197] mt_metadata.transfer_functions.io.readwrite.write_file - INFO: Wrote emtfxml_test.xml
[28]:
EMTFXML(station='CAS04', latitude=37.63, longitude=-121.47, elevation=329.39)
[29]:
 tf_cls.write_tf_file(fn="emtfxml_test.xml", file_type="zmm")
2022-06-03 17:58:39,876 [line 197] mt_metadata.transfer_functions.io.readwrite.write_file - INFO: Wrote emtfxml_test.xml
[29]:
EMTFXML(station='CAS04', latitude=37.63, longitude=-121.47, elevation=329.39)

API Reference

Time Series

Filters

Apodization Window

@author: kkappler

Module to manage windowing prior to FFT. Intended to support most apodization windows available via scipy.signal.get_window()

Supported Window types = [‘boxcar’, ‘triang’, ‘blackman’, ‘hamming’, ‘hann’,

‘bartlett’, ‘flattop’, ‘parzen’, ‘bohman’, ‘blackmanharris’, ‘nuttall’, ‘barthann’, ‘kaiser’, ‘gaussian’, ‘general_gaussian’, ‘slepian’, ‘chebwin’]

have_additional_args = {

‘kaiser’ : ‘beta’, ‘gaussian’ : ‘std’, ‘general_gaussian’ : (‘power’, ‘width’), ‘slepian’ : ‘width’, ‘chebwin’ : ‘attenuation’,

}

The Taper Config has 2 possible forms: 1. Standard form for accessing scipy.signal: [“taper_family”, “num_samples_window”, “additional_args”] 2. User-defined : for defining custom tapers

Example 1 : Standard form “taper_family” = “hamming” “num_samples_window” = 128 “additional_args” = {}

Example 2 : Standard form “taper_family” = “kaiser” “num_samples_window” = 64 “additional_args” = {“beta”:8}

Examples 3 : User Defined 2. user-defined: [“array”] In this case num_samples_window is defined by the array. “array” = [1, 2, 3, 4, 5, 4, 3, 2, 1] If “array” is non-empty then assume the user-defined case.

It is a little bit unsatisfying that the args need to be ordered for scipy.signal.get_window(). Probably use OrderedDict() for any windows that have more than one additional args.

For example “taper_family” = ‘general_gaussian’ “additional_args” = OrderedDict(“power”:1.5, “sigma”:7)

class aurora.time_series.apodization_window.ApodizationWindow(**kwargs)[source]

Bases: object

Instantiate an apodization window object. Example usages: apod_window = ApodizationWindow() taper=ApodizationWindow(taper_family=’hanning’, num_samples_window=55 )

Window factors S1, S2, CG, ENBW are modelled after Heinzel et al. p12-14 [1] Spectrum and spectral density estimation by the Discrete Fourier transform (DFT), including a comprehensive list of window functions and some new flat-top windows. G. Heinzel, A. Roudiger and R. Schilling, Max-Planck Institut fur Gravitationsphysik (Albert-Einstein-Institut) Teilinstitut Hannover February 15, 2002 See Also [2] Harris FJ. On the use of windows for harmonic analysis with the discrete Fourier transform. Proceedings of the IEEE. 1978 Jan;66(1):51-83.

Nomenclature from Heinzel et al. ENBW: Effective Noise BandWidth, see Equation (22) NENBW Normalized Equivalent Noise BandWidth, see Equation (21)

Parameters
taper_familystring

Specify the taper type - boxcar, kaiser, hanning, etc

num_samples_windowint

The number of samples in the taper

tapernumpy array

The actual window coefficients themselves. This can be passed if a particular custom window is desired.

additional_args: dictionary

These are any additional requirements scipy needs in order to generate the window.

Attributes
S1

sum of the window coefficients

S2

sum of squares of the window coefficients

apodization_factor
coherent_gain

DC gain of the window normalized by window length

nenbw

NENBW Normalized Equivalent Noise BandWidth, see Equation (21) in

num_samples_window
summary

Returns

taper

Methods

enbw(fs)

Notes that unlike NENBW, CG, S1, S2, this is not a pure property of the window -- but instead this is a property of the window combined with the sample rate.

make()

this is just a wrapper call to scipy.signal Note: see scipy.signal.get_window for a description of what is expected in args[1:].

test_linear_spectral_density_factor()

This is just a test to verify some algebra Claim: The lsd_calibration factors A (1./coherent_gain)*np.sqrt((2*dt)/(nenbw*N)) and B np.sqrt(2/(sample_rate*self.S2)) are identical.

property S1

sum of the window coefficients

property S2

sum of squares of the window coefficients

property apodization_factor
property coherent_gain

DC gain of the window normalized by window length

enbw(fs)[source]

Notes that unlike NENBW, CG, S1, S2, this is not a pure property of the window – but instead this is a property of the window combined with the sample rate. Parameters ———- fs : sampling frequency (1/dt)

Returns
make()[source]

this is just a wrapper call to scipy.signal Note: see scipy.signal.get_window for a description of what is expected in args[1:]. http://docs.scipy.org/doc/scipy/reference/ generated/scipy.signal.get_window.html

note: this is just repackaging the args so that scipy.signal.get_window() accepts all cases.

property nenbw

NENBW Normalized Equivalent Noise BandWidth, see Equation (21) in Heinzel et al 2002

property num_samples_window
property summary
Returns
out_str: str

String comprised of the taper_family, number_of_samples, and True/False if self.taper is not None

property taper
test_linear_spectral_density_factor()[source]

This is just a test to verify some algebra Claim: The lsd_calibration factors A (1./coherent_gain)*np.sqrt((2*dt)/(nenbw*N)) and B np.sqrt(2/(sample_rate*self.S2)) are identical.

Note sqrt(2*dt)==sqrt(2*sample_rate) so we can cancel these terms and A=B IFF (1./coherent_gain) * np.sqrt(1/(nenbw*N)) == 1/np.sqrt(S2) which I show in githib aurora issue #3 via . (CG**2) * NENBW *N = S2

Returns
aurora.time_series.apodization_window.main()[source]
aurora.time_series.apodization_window.test_can_inititalize_apodization_window()[source]
Returns

Decorators

Frequency Band

Frequency Band Helpers

Frequency Domain Helpers

aurora.time_series.frequency_domain_helpers.get_fft_harmonics(samples_per_window, sample_rate, one_sided=True)[source]

Works for odd and even number of points. Does not return Nyquist, does return DC component Could be midified with kwargs to support one_sided, two_sided, ignore_dc ignore_nyquist, and etc. Could actally take FrequencyBands as an argument if we wanted as well.

Parameters
samples_per_window
sample_rate
Returns

Time Axis Helpers

aurora.time_series.time_axis_helpers.decide_time_axis_method(sample_rate)[source]
aurora.time_series.time_axis_helpers.do_some_tests()[source]
aurora.time_series.time_axis_helpers.fast_arange(t0, n_samples, sample_rate)[source]
aurora.time_series.time_axis_helpers.main()[source]
aurora.time_series.time_axis_helpers.make_time_axis(t0, n_samples, sample_rate)[source]
aurora.time_series.time_axis_helpers.slow_comprehension(t0, n_samples, sample_rate)[source]
aurora.time_series.time_axis_helpers.test_generate_time_axis(t0, n_samples, sample_rate)[source]

Two obvious ways to generate an axis of timestanps here. One method is slow and more precise, the other is fast but drops some nanoseconds due to integer roundoff error.

To see this, consider the example of say 3Hz, we are 333333333ns between samples,

which drops 1ns per second if we scale a nanoseconds=np.arange(N)

The issue here is that the nanoseconds granularity forces a roundoff error,

Probably will use logic like: if there_are_integer_ns_per_sample:

time_stamps = do_it_the_fast_way()

else:

time_stamps = do_it_the_slow_way()

return time_stamps

Parameters
t0
n_samples
sample_rate
Returns

Window Helpers

Notes in google doc: https://docs.google.com/document/d/1CsRhSLXsRG8HQxM4lKNqVj-V9KA9iUQAvCOtouVzFs0/edit?usp=sharing

aurora.time_series.window_helpers.apply_fft_to_windowed_array(windowed_array)[source]

This will operate row-wise as well Parameters ———- windowed_array

Returns
aurora.time_series.window_helpers.available_number_of_windows_in_array(n_samples_array, n_samples_window, n_advance)[source]
Parameters
n_samples_array: int

The length of the time series

n_samples_window: int

The length of the window (in samples)

n_advance: int

The number of samples the window advances at each step

Returns
available_number_of_strides: int

The number of windows the time series will yield

aurora.time_series.window_helpers.check_all_sliding_window_functions_are_equivalent()[source]

simple sanity check that runs each sliding window function on a small array and confirms the results are numerically identical. Note that striding window will return int types where others return float. Returns ——-

aurora.time_series.window_helpers.do_some_tests()[source]
aurora.time_series.window_helpers.main()[source]
aurora.time_series.window_helpers.sliding_window_crude(data, num_samples_window, num_samples_advance, num_windows=None)[source]
Parameters
data: np.ndarray

The time series data to be windowed

num_samples_window: int

The length of the window (in samples)

num_samples_advance: int

The number of samples the window advances at each step

num_windows: int

The number of windows to “take”. Must be less or equal to the number of available windows.

Returns
output_array: numpy.ndarray

The windowed time series

aurora.time_series.window_helpers.sliding_window_numba(data, num_samples_window, num_samples_advance, num_windows)[source]
Parameters
data: np.ndarray

The time series data to be windowed

num_samples_window: int

The length of the window (in samples)

num_samples_advance: int

The number of samples the window advances at each step

num_windows: int

The number of windows to “take”.

Returns
output_array: numpy.ndarray

The windowed time series

aurora.time_series.window_helpers.striding_window(data, num_samples_window, num_samples_advance, num_windows=None)[source]

Applies a striding window to an array. We use 1D arrays here. Note that this method is extendable to N-dimensional arrays as was once shown at http://www.johnvinyard.com/blog/?p=268

Karl has an implementation of this code but chose to restict to 1D here. This is becuase of several warnings encountered, on the notes of stride_tricks.py, as well as for example here: https://stackoverflow.com/questions/4936620/using-strides-for-an-efficient-moving-average-filter

While we can possibly setup Aurora so that no copies of the strided window are made downstream, we cannot guarantee that another user may not add methods that require copies. For robustness we will use 1d implementation only for now.

Another clean example of this method can be found in the razorback codes from brgm.

result is 2d: result[i] is the i-th window

>>> sliding_window(np.arange(15), 4, 3, 2)
array([[0, 1, 2],
       [2, 3, 4],
       [4, 5, 6],
       [6, 7, 8]])
Parameters
data: np.ndarray

The time series data to be windowed

num_samples_window: int

The length of the window (in samples)

num_samples_advance: int

The number of samples the window advances at each step

num_windows: int

The number of windows to “take”. Must be less or equal to the number of available windows.

Returns
strided_window: numpy.ndarray

The windowed time series

aurora.time_series.window_helpers.test_apply_taper()[source]

Windowed Time Series

Windowing Scheme

Transfer Function

Plot

Regression

Base

EMTF Z File Helpers

These methods can possibly be moved under mt_metadata, or mth5

They extract info needed to setup emtf_z files.

aurora.transfer_function.emtf_z_file_helpers.clip_bands_from_z_file(z_path, n_bands_clip, output_z_path=None, n_sensors=5)[source]

This function takes a z_file and clips periods off the end of it. It can come in handy sometimes – specifically for manipulating matlab results of synthetic data.

Parameters
z_path: Path or str

path to the z_file to read in and clip periods from

n_periods_clip: integer

how many periods to clip from the end of the zfile

overwrite: bool

whether to overwrite the zfile or rename it

n_sensors
Returns
aurora.transfer_function.emtf_z_file_helpers.get_default_orientation_block(n_ch=5)[source]

Helper function used when working with matlab structs which do not have enough info to make headers

Parameters
n_ch: int

number of channels at the station

Returns
orientation_strs: list

List of text strings, one per channel

aurora.transfer_function.emtf_z_file_helpers.make_orientation_block_of_z_file(run_obj, channel_list=None)[source]

Replicates emtz z-file metadata about orientation like this: 1 0.00 0.00 tes Hx 2 90.00 0.00 tes Hy 3 0.00 0.00 tes Hz 4 0.00 0.00 tes Ex 5 90.00 0.00 tes Ey

based on this fortran snippet:

write(3, 115) k, orient(1, k), orient(2, k), stname(1: 3), chid(k)

format(i5, 1x, f8.2, 1x, f8.2, 1x, a3, 2x, a6) #Fortran Format

Parameters
run_obj: mth5.groups.master_station_run_channel.RunGroup

Container with metadata about the channels

Returns
output_strings: list (of strings)

Each element of the list corresponds to one channel, and is a block of text for the emtf z-file with the channel orientation, name and associated station

aurora.transfer_function.emtf_z_file_helpers.merge_tf_collection_to_match_z_file(aux_data, tf_collection)[source]

Currently this is only used for the synthtetic test, but maybe useful for other tests. Given data from a z_file, and a tf_collection, the tf_collection may have several TF estimates at the same frequency from multiple decimation levels. This tries to make a single array as a function of period for all rho and phi

Parameters
aux_data: merge_tf_collection_to_match_z_file

Object representing a z-file

tf_collection: aurora.transfer_function.transfer_function_collection
.TransferFunctionCollection

Object representing the transfer function returnd from the aurora processing

Returns
result: dict of dicts

Keyed by [“rho”, “phi”], below each of these is an [“xy”, “yx”,] entry. The lowest level entries are numpy arrays.

Iter Control

follows Gary’s IterControl.m in iris_mt_scratch/egbert_codes-20210121T193218Z-001/egbert_codes/matlabPrototype_10-13-20/TF/classes

class aurora.transfer_function.regression.iter_control.IterControl(max_number_of_iterations=10, max_number_of_redescending_iterations=2, **kwargs)[source]

Bases: object

Attributes
continue_redescending
correction_factor

TODO: This is an RME specific property.

Methods

converged(b, b0)

Parameters

property continue_redescending
converged(b, b0)[source]
Parameters
bcomplex-valued numpy array

the most recent regression estimate

b0complex-valued numpy array

The previous regression estimate

Returns
converged: bool

True of the regression has terminated, False otherwise

Notes:
The variable maximum_change finds the maximum amplitude component of the vector
1-b/b0. Looking at the formula, one might want to cast this instead as
1 - abs(b/b0), however, that will be insensitive to phase changes in b,
which is complex valued. The way it is coded np.max(np.abs(1 - b / b0)) is
correct as it stands.
property correction_factor

TODO: This is an RME specific property. Suggest move r0, u0 and this method into an RME-config class.

See notes on usage in transfer_function.regression.helper_functions.rme_beta

Returns
correction_factorfloat

correction factor used for scaling the residual error_variance

Transfer Function Collection

Transfer Function Header

follows Gary’s TFHeader.m iris_mt_scratch/egbert_codes-20210121T193218Z-001/egbert_codes/matlabPrototype_10-13-20/TF/classes

class aurora.transfer_function.transfer_function_header.TransferFunctionHeader(**kwargs)[source]

Bases: object

class for storing metadata for a TF estimate

This class should inherit the metadata from the remote and reference stations. As of 2021-07-20 the class functions with only the station_id and channel_id values.

<See Issue #41> </See Issue #41>

Attributes
local_channels
local_station
local_station_id
num_input_channels
num_output_channels
reference_station_id
property local_channels
property local_station
property local_station_id
property num_input_channels
property num_output_channels
property reference_station_id

TTFZ

Pipelines

Process MTH5

Time Series Helpers

Transfer Function Helpers

Interval

Source https://github.com/internetarchive/analyze_ocr/blob/master/interval.py Liscence Not Specified

Provides the Interval and IntervalSet classes

The interval module provides the Interval and IntervalSet data types. Intervals describe continuous ranges that can be open, closed, half-open, or infinite. IntervalSets contain zero to many disjoint sets of Intervals.

Intervals don’t have to pertain to numbers. They can contain any data that is comparable via the Python operators <, <=, ==, >=, and >. Here’s an example of how strings can be used with Intervals:

>>> volume1 = Interval.between("A", "Foe")
>>> volume2 = Interval.between("Fog", "McAfee")
>>> volume3 = Interval.between("McDonalds", "Space")
>>> volume4 = Interval.between("Spade", "Zygote")
>>> encyclopedia = IntervalSet([volume1, volume2, volume3, volume4])
>>> mySet = IntervalSet([volume1, volume3, volume4])
>>> "Meteor" in encyclopedia
True
>>> "Goose" in encyclopedia
True
>>> "Goose" in mySet
False
>>> volume2 in (encyclopedia ^ mySet)
True

Here’s an example of how times can be used with Intervals:

>>> officeHours = IntervalSet.between("08:00", "17:00")
>>> myLunch = IntervalSet.between("11:30", "12:30")
>>> myHours = IntervalSet.between("08:30", "19:30") - myLunch
>>> myHours.issubset(officeHours)
False
>>> "12:00" in myHours
False
>>> "15:30" in myHours
True
>>> inOffice = officeHours & myHours
>>> print inOffice
['08:30'..'11:30'),('12:30'..'17:00']
>>> overtime = myHours - officeHours
>>> print overtime
('17:00'..'19:30']
class aurora.interval.BaseIntervalSet(items=[])[source]

Bases: object

Base class for IntervalSet and FrozenIntervalSet.

Methods

all()

Returns an interval set containing all values

between(a, b[, closed])

Returns an IntervalSet of all values between a and b.

bounds()

Returns an interval that encompasses the entire BaseIntervalSet

copy()

Returns a copy of the object

difference(other)

Returns the difference between the object and the given object

empty()

Returns an interval set containing no values.

greater_than(n)

Returns an IntervalSet containing values greater than the given value

greater_than_or_equal_to(n)

Returns an IntervalSet containing values greater than or equal to the given value

intersection(other)

Returns the intersection between the object and the given value

issubset(other)

Tells if the given object is a subset of the object

issuperset(other)

Tells whether the given object is a superset of the object

less_than(n)

Returns an IntervalSet containing values less than the given value

less_than_or_equal_to(n[, closed])

Returns an IntervalSet containing values less than or equal to the given value

lower_bound()

Returns the lower boundary of the BaseIntervalSet

lower_closed()

Returns a boolean telling whether the lower bound is closed or not

not_equal_to(n)

Returns an IntervalSet of all values not equal to n

symmetric_difference(other)

Returns the exclusive or of the given value with the object

union(other)

Returns the union of the given value with the object

upper_bound()

Returns the upper boundary of the BaseIntervalSet

upper_closed()

Returns a boolean telling whether the upper bound is closed or not

classmethod all()[source]

Returns an interval set containing all values

>>> print IntervalSet.all()
(...)
classmethod between(a, b, closed=True)[source]

Returns an IntervalSet of all values between a and b.

If closed is True, then the endpoints are included; otherwise, they aren’t.

>>> print IntervalSet.between(0, 100)
[0..100]
>>> print IntervalSet.between(-1, 1)
[-1..1]
bounds()[source]

Returns an interval that encompasses the entire BaseIntervalSet

>>> print IntervalSet([Interval.between(4, 6), 2, 12]).bounds()
[2..12]
>>> print IntervalSet().bounds()
<Empty>
>>> print IntervalSet.all().bounds()
(...)
copy()[source]

Returns a copy of the object

>>> s = IntervalSet(
...   [7, 2, 3, 2, 6, 2, Interval.greater_than(3)])
>>> s2 = s.copy()
>>> s == s2
True
>>> s = FrozenIntervalSet(
...   [7, 2, 3, 2, 6, 2, Interval.greater_than(3)])
>>> s2 = s.copy()
>>> s == s2
True
difference(other)[source]

Returns the difference between the object and the given object

Returns all values of self minus all matching values in other. It is identical to the - operator, only it accepts any iterable as the operand.

>>> negatives = IntervalSet.less_than(0)
>>> positives = IntervalSet.greater_than(0)
>>> naturals  = IntervalSet.greater_than_or_equal_to(0)
>>> evens     = IntervalSet([-8, -6, -4, -2, 0, 2, 4, 6, 8])
>>> zero      = IntervalSet([0])
>>> nonzero   = IntervalSet.not_equal_to(0)
>>> empty     = IntervalSet.empty()
>>> all       = IntervalSet.all()
>>> print evens.difference(nonzero)
0
>>> print empty.difference(naturals)
<Empty>
>>> print zero.difference(naturals)
<Empty>
>>> print positives.difference(zero)
(0...)
>>> print naturals.difference(negatives)
[0...)
>>> print all.difference(zero)
(...0),(0...)
>>> all.difference(zero) == nonzero
True
>>> naturals.difference([0]) == positives
True
classmethod empty()[source]

Returns an interval set containing no values.

>>> print IntervalSet.empty()
<Empty>
classmethod greater_than(n)[source]

Returns an IntervalSet containing values greater than the given value

>>> print IntervalSet.greater_than(0)
(0...)
>>> print IntervalSet.greater_than(-23)
(-23...)
classmethod greater_than_or_equal_to(n)[source]

Returns an IntervalSet containing values greater than or equal to the given value

>>> print IntervalSet.greater_than_or_equal_to(0)
[0...)
>>> print IntervalSet.greater_than_or_equal_to(-23)
[-23...)
intersection(other)[source]

Returns the intersection between the object and the given value

This function returns the intersection of self and other. It is identical to the & operator, except this function accepts any iterable as an operand, and & accepts only another BaseIntervalSet.

>>> negatives = IntervalSet.less_than(0)
>>> positives = IntervalSet.greater_than(0)
>>> naturals  = IntervalSet.greater_than_or_equal_to(0)
>>> evens     = IntervalSet([-8, -6, -4, -2, 0, 2, 4, 6, 8])
>>> zero      = IntervalSet([0])
>>> nonzero   = IntervalSet.not_equal_to(0)
>>> empty     = IntervalSet.empty()
>>> print naturals.intersection(naturals)
[0...)
>>> print evens.intersection(zero)
0
>>> print negatives.intersection(zero)
<Empty>
>>> print nonzero.intersection(positives)
(0...)
>>> print empty.intersection(zero)
<Empty>
issubset(other)[source]

Tells if the given object is a subset of the object

Returns true if self is a subset of other. other can be any iterable object.

>>> zero = IntervalSet([0])
>>> positives = IntervalSet.greater_than(0)
>>> naturals = IntervalSet.greater_than_or_equal_to(0)
>>> negatives = IntervalSet.less_than(0)
>>> r = IntervalSet.between(3, 6)
>>> r2 = IntervalSet.between(-8, -2)
>>> zero.issubset(positives)
False
>>> zero.issubset(naturals)
True
>>> positives.issubset(zero)
False
>>> r.issubset(zero)
False
>>> r.issubset(positives)
True
>>> positives.issubset(r)
False
>>> negatives.issubset(IntervalSet.all())
True
>>> r2.issubset(negatives)
True
>>> negatives.issubset(positives)
False
>>> zero.issubset([0, 1, 2, 3])
True
issuperset(other)[source]

Tells whether the given object is a superset of the object

Returns true if self is a superset of other. other can be any iterable object.

>>> zero = IntervalSet([0])
>>> positives = IntervalSet.greater_than(0)
>>> naturals = IntervalSet.greater_than_or_equal_to(0)
>>> negatives = IntervalSet.less_than(0)
>>> r = IntervalSet.between(3, 6)
>>> r2 = IntervalSet.between(-8, -2)
>>> zero.issuperset(positives)
False
>>> zero.issuperset(naturals)
False
>>> positives.issuperset(zero)
False
>>> r.issuperset(zero)
False
>>> r.issuperset(positives)
False
>>> positives.issuperset(r)
True
>>> negatives.issuperset(IntervalSet.all())
False
>>> r2.issuperset(negatives)
False
>>> negatives.issuperset(positives)
False
>>> negatives.issuperset([-2, -632])
True
classmethod less_than(n)[source]

Returns an IntervalSet containing values less than the given value

>>> print IntervalSet.less_than(0)
(...0)
>>> print IntervalSet.less_than(-23)
(...-23)
classmethod less_than_or_equal_to(n, closed=False)[source]

Returns an IntervalSet containing values less than or equal to the given value

>>> print IntervalSet.less_than_or_equal_to(0)
(...0]
>>> print IntervalSet.less_than_or_equal_to(-23)
(...-23]
lower_bound()[source]

Returns the lower boundary of the BaseIntervalSet

>>> IntervalSet([Interval.between(4, 6), 2, 12]).lower_bound()
2
>>> IntervalSet().lower_bound()
Traceback (most recent call last):
    ...
IndexError: The BaseIntervalSet is empty
>>> IntervalSet.all().lower_bound()
-Inf
lower_closed()[source]

Returns a boolean telling whether the lower bound is closed or not

>>> IntervalSet([Interval.between(4, 6), 2, 12]).lower_closed()
True
>>> IntervalSet().lower_closed()
Traceback (most recent call last):
    ...
IndexError: The BaseIntervalSet is empty
>>> IntervalSet.all().lower_closed()
False
classmethod not_equal_to(n)[source]

Returns an IntervalSet of all values not equal to n

>>> print IntervalSet.not_equal_to(0)
(...0),(0...)
>>> print IntervalSet.not_equal_to(-23)
(...-23),(-23...)
symmetric_difference(other)[source]

Returns the exclusive or of the given value with the object

This function returns the exclusive or of two IntervalSets. It is identical to the ^ operator, except it accepts any iterable object for the operand.

>>> negatives = IntervalSet.less_than(0)
>>> positives = IntervalSet.greater_than(0)
>>> naturals  = IntervalSet.greater_than_or_equal_to(0)
>>> evens     = IntervalSet([-8, -6, -4, -2, 0, 2, 4, 6, 8])
>>> zero      = IntervalSet([0])
>>> nonzero   = IntervalSet.not_equal_to(0)
>>> empty     = IntervalSet.empty()
>>> print nonzero.symmetric_difference(naturals)
(...0]
>>> print zero.symmetric_difference(negatives)
(...0]
>>> print positives.symmetric_difference(empty)
(0...)
>>> print evens.symmetric_difference(zero)
-8,-6,-4,-2,2,4,6,8
>>> print evens.symmetric_difference(range(0, 9, 2))
-8,-6,-4,-2
union(other)[source]

Returns the union of the given value with the object

This function returns the union of a BaseIntervalSet and an iterable object. It is identical to the | operator, except that | only accepts a BaseIntervalSet operand and union accepts any iterable.

>>> negatives = IntervalSet.less_than(0)
>>> positives = IntervalSet.greater_than(0)
>>> naturals  = IntervalSet.greater_than_or_equal_to(0)
>>> evens     = IntervalSet([-8, -6, -4, -2, 0, 2, 4, 6, 8])
>>> zero      = IntervalSet([0])
>>> nonzero   = IntervalSet.not_equal_to(0)
>>> empty     = IntervalSet.empty()
>>> all       = IntervalSet.all()
>>> print evens.union(positives)
-8,-6,-4,-2,[0...)
>>> print negatives.union(zero)
(...0]
>>> print empty.union(negatives)
(...0)
>>> print empty.union(naturals)
[0...)
>>> print nonzero.union(evens)
(...)
>>> print negatives.union(range(5))
(...0],1,2,3,4
upper_bound()[source]

Returns the upper boundary of the BaseIntervalSet

>>> IntervalSet([Interval.between(4, 6), 2, 12]).upper_bound()
12
>>> IntervalSet().upper_bound()
Traceback (most recent call last):
    ...
IndexError: The BaseIntervalSet is empty
>>> IntervalSet.all().upper_bound()
Inf
upper_closed()[source]

Returns a boolean telling whether the upper bound is closed or not

>>> IntervalSet([Interval.between(4, 6), 2, 12]).upper_closed()
True
>>> IntervalSet().upper_closed()
Traceback (most recent call last):
    ...
IndexError: The BaseIntervalSet is empty
>>> IntervalSet.all().upper_closed()
False
class aurora.interval.FrozenIntervalSet(items=[])[source]

Bases: aurora.interval.BaseIntervalSet

An immutable version of BaseIntervalSet

FrozenIntervalSet is like IntervalSet, only add and remove are not implemented, and hashes can be generated.

>>> fs = FrozenIntervalSet([3, 6, 2, 4])
>>> fs.add(12)
Traceback (most recent call last):
  ...
AttributeError: 'FrozenIntervalSet' object has no attribute 'add'
>>> fs.remove(4)
Traceback (most recent call last):
  ...
AttributeError: 'FrozenIntervalSet' object has no attribute 'remove'
>>> fs.clear()
Traceback (most recent call last):
  ...
AttributeError: 'FrozenIntervalSet' object has no attribute 'clear'

Because FrozenIntervalSets are immutable, they can be used as a dictionary key.

>>> d = {
...   FrozenIntervalSet([3, 66]) : 52,
...   FrozenIntervalSet.less_than(3) : 3}

Methods

all()

Returns an interval set containing all values

between(a, b[, closed])

Returns an IntervalSet of all values between a and b.

bounds()

Returns an interval that encompasses the entire BaseIntervalSet

copy()

Duplicates the object

difference(other)

Returns the difference between the object and the given object

empty()

Returns an interval set containing no values.

greater_than(n)

Returns an IntervalSet containing values greater than the given value

greater_than_or_equal_to(n)

Returns an IntervalSet containing values greater than or equal to the given value

intersection(other)

Returns the intersection between the object and the given value

issubset(other)

Tells if the given object is a subset of the object

issuperset(other)

Tells whether the given object is a superset of the object

less_than(n)

Returns an IntervalSet containing values less than the given value

less_than_or_equal_to(n[, closed])

Returns an IntervalSet containing values less than or equal to the given value

lower_bound()

Returns the lower boundary of the BaseIntervalSet

lower_closed()

Returns a boolean telling whether the lower bound is closed or not

not_equal_to(n)

Returns an IntervalSet of all values not equal to n

symmetric_difference(other)

Returns the exclusive or of the given value with the object

union(other)

Returns the union of the given value with the object

upper_bound()

Returns the upper boundary of the BaseIntervalSet

upper_closed()

Returns a boolean telling whether the upper bound is closed or not

copy()[source]

Duplicates the object

For FrozenIntervalSet objects, since they’re immutable, a reference, not a copy, of self is returned.

>>> s = FrozenIntervalSet(
...   [7, 2, 3, 2, 6, 2, Interval.greater_than(3)])
>>> s2 = s.copy()
>>> s == s2
True
>>> id(s) == id(s2)
True
class aurora.interval.Interval(lower_bound=- Inf, upper_bound=Inf, **kwargs)[source]

Bases: object

Represents a continuous range of values

An Interval is composed of the lower bound, a closed lower bound flag, an upper bound, and a closed upper bound flag. The attributes are called lower_bound, lower_closed, upper_bound, and upper_closed, respectively. For an infinite interval, the bound is set to inf or -inf. IntervalSets are composed of zero to many Intervals.

Methods

adjacent_to(other)

Tells whether an Interval is adjacent to the object without overlap

all()

Returns an interval encompassing all values

between(a, b[, closed])

Returns an interval between two values

comes_before(other)

Tells whether an interval lies before the object

duration()

@note: added 20140618 kkappler returns the duration of interval

equal_to(a)

Returns an point interval

greater_than(a)

Returns interval of all values greater than the given value

greater_than_or_equal_to(a)

Returns interval of all values greater than or equal to the given value

join(other)

Combines two continous Intervals

less_than(a)

Returns interval of all values less than the given value

less_than_or_equal_to(a)

Returns an interval containing the given values and everything less

none()

Returns an empty interval

overlaps(other)

Tells whether the given interval overlaps the object

pad(pad_width)

@note: added 20140618 kkappler returns a padded interval; Intent was to add a little so that open-intervals, or adjacent intervals would easily make an interval set

adjacent_to(other)[source]

Tells whether an Interval is adjacent to the object without overlap

Returns True if self is adjacent to other, meaning that if they were joined, there would be no discontinuity. They cannot overlap.

>>> r1  = Interval.less_than(-100)
>>> r2  = Interval.less_than_or_equal_to(-100)
>>> r3  = Interval.less_than(100)
>>> r4  = Interval.less_than_or_equal_to(100)
>>> r5  = Interval.all()
>>> r6  = Interval.between(-100, 100, False)
>>> r7  = Interval(-100, 100, lower_closed=False)
>>> r8  = Interval.greater_than(-100)
>>> r9  = Interval.equal_to(-100)
>>> r10 = Interval(-100, 100, upper_closed=False)
>>> r11 = Interval.between(-100, 100)
>>> r12 = Interval.greater_than_or_equal_to(-100)
>>> r13 = Interval.greater_than(100)
>>> r14 = Interval.equal_to(100)
>>> r15 = Interval.greater_than_or_equal_to(100)
>>> r1.adjacent_to(r6)
False
>>> r6.adjacent_to(r11)
False
>>> r7.adjacent_to(r9)
True
>>> r3.adjacent_to(r10)
False
>>> r5.adjacent_to(r14)
False
>>> r6.adjacent_to(r15)
True
>>> r1.adjacent_to(r8)
False
>>> r12.adjacent_to(r14)
False
>>> r6.adjacent_to(r13)
False
>>> r2.adjacent_to(r15)
False
>>> r1.adjacent_to(r4)
False
classmethod all()[source]

Returns an interval encompassing all values

>>> print Interval.all()
(...)
classmethod between(a, b, closed=True)[source]

Returns an interval between two values

Returns an interval between values a and b. If closed is True, then the endpoints are included. Otherwise, the endpoints are excluded.

>>> print Interval.between(2, 4)
[2..4]
>>> print Interval.between(2, 4, False)
(2..4)
comes_before(other)[source]

Tells whether an interval lies before the object

self comes before other when sorted if its lower bound is less than other’s smallest value. If the smallest value is the same, then the Interval with the smallest upper bound comes first. Otherwise, they are equal.

>>> Interval.equal_to(1).comes_before(Interval.equal_to(4))
True
>>> Interval.less_than_or_equal_to(1).comes_before(Interval.equal_to(4))
True
>>> Interval.less_than_or_equal_to(5).comes_before(
...   Interval.less_than(5))
False
>>> Interval.less_than(5).comes_before(
...   Interval.less_than_or_equal_to(5))
True
>>> Interval.all().comes_before(Interval.all())
False
duration()[source]

@note: added 20140618 kkappler returns the duration of interval

classmethod equal_to(a)[source]

Returns an point interval

Returns an interval containing only a.

>>> print Interval.equal_to(32)
32
classmethod greater_than(a)[source]

Returns interval of all values greater than the given value

>>> print Interval.greater_than(32)
(32...)
classmethod greater_than_or_equal_to(a)[source]

Returns interval of all values greater than or equal to the given value

>>> print Interval.greater_than_or_equal_to(32)
[32...)
join(other)[source]

Combines two continous Intervals

Combines two continuous Intervals into one Interval. If the two Intervals are disjoint, then an exception is raised.

>>> r1  = Interval.less_than(-100)
>>> r2  = Interval.less_than_or_equal_to(-100)
>>> r3  = Interval.less_than(100)
>>> r4  = Interval.less_than_or_equal_to(100)
>>> r5  = Interval.all()
>>> r6  = Interval.between(-100, 100, False)
>>> r7  = Interval(-100, 100, lower_closed=False)
>>> r8  = Interval.greater_than(-100)
>>> r9  = Interval.equal_to(-100)
>>> r10 = Interval(-100, 100, upper_closed=False)
>>> r11 = Interval.between(-100, 100)
>>> r12 = Interval.greater_than_or_equal_to(-100)
>>> r13 = Interval.greater_than(100)
>>> r14 = Interval.equal_to(100)
>>> r15 = Interval.greater_than_or_equal_to(100)
>>> print r13.join(r15)
[100...)
>>> print r7.join(r6)
(-100..100]
>>> print r11.join(r2)
(...100]
>>> print r4.join(r15)
(...)
>>> print r8.join(r8)
(-100...)
>>> print r3.join(r7)
(...100]
>>> print r5.join(r10)
(...)
>>> print r9.join(r1)
(...-100]
>>> print r12.join(r5)
(...)
>>> print r13.join(r1)
Traceback (most recent call last):
...
ArithmeticError: The Intervals are disjoint.
>>> print r14.join(r2)
Traceback (most recent call last):
...
ArithmeticError: The Intervals are disjoint.
classmethod less_than(a)[source]

Returns interval of all values less than the given value

Returns an interval containing all values less than a. If closed is True, then all values less than or equal to a are returned.

>>> print Interval.less_than(32)
(...32)
classmethod less_than_or_equal_to(a)[source]

Returns an interval containing the given values and everything less

>>> print Interval.less_than_or_equal_to(32)
(...32]
classmethod none()[source]

Returns an empty interval

>>> print Interval.none()
<Empty>
overlaps(other)[source]

Tells whether the given interval overlaps the object

Returns True if the one Interval overlaps another. If they are immediately adjacent, then this returns False. Use the adjacent_to function for testing for adjacent Intervals.

>>> r1  = Interval.less_than(-100)
>>> r2  = Interval.less_than_or_equal_to(-100)
>>> r3  = Interval.less_than(100)
>>> r4  = Interval.less_than_or_equal_to(100)
>>> r5  = Interval.all()
>>> r6  = Interval.between(-100, 100, False)
>>> r7  = Interval(-100, 100, lower_closed=False)
>>> r8  = Interval.greater_than(-100)
>>> r9  = Interval.equal_to(-100)
>>> r10 = Interval(-100, 100, upper_closed=False)
>>> r11 = Interval.between(-100, 100)
>>> r12 = Interval.greater_than_or_equal_to(-100)
>>> r13 = Interval.greater_than(100)
>>> r14 = Interval.equal_to(100)
>>> r15 = Interval.greater_than_or_equal_to(100)
>>> r8.overlaps(r9)
False
>>> r12.overlaps(r6)
True
>>> r7.overlaps(r8)
True
>>> r8.overlaps(r4)
True
>>> r14.overlaps(r11)
True
>>> r10.overlaps(r13)
False
>>> r5.overlaps(r1)
True
>>> r5.overlaps(r2)
True
>>> r15.overlaps(r6)
False
>>> r3.overlaps(r1)
True
pad(pad_width)[source]

@note: added 20140618 kkappler returns a padded interval; Intent was to add a little so that open-intervals, or adjacent intervals would easily make an interval set

class aurora.interval.IntervalSet(items=[])[source]

Bases: aurora.interval.BaseIntervalSet

The mutable version of BaseIntervalSet

IntervalSet is a class representing sets of continuous values, as opposed to a discrete set, which is already implemented by the set type in Python.

IntervalSets can be bounded, unbounded, and non-continuous. They were designed to accomodate any sort of mathematical set dealing with continuous values. This will usually mean numbers, but any Python type that has valid comparison operations can be used in an IntervalSet.

Because IntervalSets are mutable, it cannot be used as a dictionary key.

>>> {IntervalSet([3, 66]) : 52}
Traceback (most recent call last):
    ...
TypeError: unhashable instance

Methods

add(obj)

Adds an Interval or discrete value to the object

all()

Returns an interval set containing all values

between(a, b[, closed])

Returns an IntervalSet of all values between a and b.

bounds()

Returns an interval that encompasses the entire BaseIntervalSet

clear()

Removes all Intervals from the object

copy()

Returns a copy of the object

difference(other)

Returns the difference between the object and the given object

difference_update(other)

Removes any elements in the given value from the object

discard(obj)

Removes a value from the object

empty()

Returns an interval set containing no values.

greater_than(n)

Returns an IntervalSet containing values greater than the given value

greater_than_or_equal_to(n)

Returns an IntervalSet containing values greater than or equal to the given value

intersection(other)

Returns the intersection between the object and the given value

intersection_update(other)

Removes values not found in the parameter

issubset(other)

Tells if the given object is a subset of the object

issuperset(other)

Tells whether the given object is a superset of the object

less_than(n)

Returns an IntervalSet containing values less than the given value

less_than_or_equal_to(n[, closed])

Returns an IntervalSet containing values less than or equal to the given value

lower_bound()

Returns the lower boundary of the BaseIntervalSet

lower_closed()

Returns a boolean telling whether the lower bound is closed or not

not_equal_to(n)

Returns an IntervalSet of all values not equal to n

pop()

Returns and discards an Interval or value from the IntervalSet

remove(obj)

Removes a value from the object

symmetric_difference(other)

Returns the exclusive or of the given value with the object

symmetric_difference_update(other)

Updates the object as though doing an xor with the parameter

union(other)

Returns the union of the given value with the object

update(other)

Adds elements from the given value to the object

upper_bound()

Returns the upper boundary of the BaseIntervalSet

upper_closed()

Returns a boolean telling whether the upper bound is closed or not

add(obj)[source]

Adds an Interval or discrete value to the object

>>> r = IntervalSet()
>>> r.add(4)
>>> print r
4
>>> r.add(Interval(23, 39, lower_closed=False))
>>> print r
4,(23..39]
>>> r.add(Interval.less_than(25))
>>> print r
(...39]
clear()[source]

Removes all Intervals from the object

>>> s = IntervalSet([2, 7, Interval.greater_than(8), 2, 6, 34])
>>> print s
2,6,7,(8...)
>>> s.clear()
>>> print s
<Empty>
difference_update(other)[source]

Removes any elements in the given value from the object

This function removes the elements in other from self. other can be any iterable object.

>>> r = IntervalSet.all()
>>> r.difference_update([4])
>>> print r
(...4),(4...)
>>> r.difference_update(
...   IntervalSet([Interval(23, 39, lower_closed=False)]))
>>> print r
(...4),(4..23],(39...)
>>> r.difference_update(IntervalSet.less_than(25))
>>> print r
(39...)
>>> r2 = IntervalSet.all()
>>> r.difference_update(r2)
>>> print r
<Empty>
discard(obj)[source]

Removes a value from the object

This function removes an Interval or discrete value from an IntervalSet.

>>> r = IntervalSet.all()
>>> r.discard(4)
>>> print r
(...4),(4...)
>>> r.discard(Interval(23, 39, lower_closed=False))
>>> print r
(...4),(4..23],(39...)
>>> r.discard(Interval.less_than(25))
>>> print r
(39...)
intersection_update(other)[source]

Removes values not found in the parameter

Removes elements not found in other. other can be any iterable object

>>> r = IntervalSet.all()
>>> r.intersection_update([4])
>>> print r
4
>>> r = IntervalSet.all()
>>> r.intersection_update(
...   IntervalSet([Interval(23, 39, lower_closed=False)]))
>>> print r
(23..39]
>>> r.intersection_update(IntervalSet.less_than(25))
>>> print r
(23..25)
>>> r2 = IntervalSet.all()
>>> r.intersection_update(r2)
>>> print r
(23..25)
pop()[source]

Returns and discards an Interval or value from the IntervalSet

>>> s = IntervalSet([7, Interval.less_than(2), 2, 0])
>>> l = []
>>> l.append(str(s.pop()))
>>> l.append(str(s.pop()))
>>> "(...2)" in l
False
>>> "(...2]" in l
True
>>> "7" in l
True
>>> print s
<Empty>
>>> i = s.pop()
Traceback (most recent call last):
    ...
KeyError: 'pop from an empty IntervalSet'
remove(obj)[source]

Removes a value from the object

This function removes an Interval, discrete value, or set from an IntervalSet. If the object is not in the set, a KeyError is raised.

>>> r = IntervalSet.all()
>>> r.remove(4)
>>> print r
(...4),(4...)
>>> r.remove(Interval(23, 39, lower_closed=False))
>>> print r
(...4),(4..23],(39...)
>>> r.remove(Interval.less_than(25))
Traceback (most recent call last):
    ...
KeyError: '(...25)'
symmetric_difference_update(other)[source]

Updates the object as though doing an xor with the parameter

Removes elements found in other and adds elements in other that are not in self. other can be any iterable object.

>>> r = IntervalSet.empty()
>>> r.symmetric_difference_update([4])
>>> print r
4
>>> r.symmetric_difference_update(
...   IntervalSet([Interval(23, 39, lower_closed=False)]))
>>> print r
4,(23..39]
>>> r.symmetric_difference_update(IntervalSet.less_than(25))
>>> print r
(...4),(4..23],[25..39]
>>> r2 = IntervalSet.all()
>>> r.symmetric_difference_update(r2)
>>> print r
4,(23..25),(39...)
update(other)[source]

Adds elements from the given value to the object

Adds elements from other to self. other can be any iterable object.

>>> r = IntervalSet()
>>> r.update([4])
>>> print r
4
>>> r.update(IntervalSet([Interval(23, 39, lower_closed=False)]))
>>> print r
4,(23..39]
>>> r.update(IntervalSet.less_than(25))
>>> print r
(...39]
>>> r2 = IntervalSet.all()
>>> r.update(r2)
>>> print r
(...)
class aurora.interval.Largest[source]

Bases: object

Class representing the universal largest value

This type doesn’t do much; it implements a pseudo-value that’s larger than everything but itself.

>>> infinity = Largest()
>>> greatest = Largest()
>>> 6234 < infinity
True
>>> 6234 == infinity
False
>>> 6234 > infinity
False
>>> infinity > infinity
False
>>> infinity == greatest
True
class aurora.interval.Smallest[source]

Bases: object

Represents the smallest value

This type doesn’t do much; it implements a pseudo-value that’s smaller than everything but itself.

>>> negInf = Smallest()
>>> smallest = Smallest()
>>> -264 < negInf
False
>>> -264 == negInf
False
>>> -264 > negInf
True
>>> negInf < negInf
False
>>> negInf == smallest
True
class aurora.interval.TimePeriod(**kwargs)[source]

Bases: aurora.interval.Interval

Methods

adjacent_to(other)

Tells whether an Interval is adjacent to the object without overlap

all()

Returns an interval encompassing all values

between(a, b[, closed])

Returns an interval between two values

comes_before(other)

Tells whether an interval lies before the object

equal_to(a)

Returns an point interval

greater_than(a)

Returns interval of all values greater than the given value

greater_than_or_equal_to(a)

Returns interval of all values greater than or equal to the given value

join(other)

Combines two continous Intervals

less_than(a)

Returns interval of all values less than the given value

less_than_or_equal_to(a)

Returns an interval containing the given values and everything less

none()

Returns an empty interval

overlaps(other)

Tells whether the given interval overlaps the object

pad(pad_width)

@note: added 20140618 kkappler returns a padded interval; Intent was to add a little so that open-intervals, or adjacent intervals would easily make an interval set

duration

duration()[source]
aurora.interval.generate_interval_list(startTime, endTime, delta)[source]

generic function used for specifying timeintervals to load probably place in gmi.core.interval

Ideally would support endtime, number of segments or other

aurora.interval.merge_interval_list(interval_list)[source]

Can think of a stack of unassembled parts. Put the first part in your left hand, then draw the next part in your right. Check if the pieces mate, if so, attach and keep in your left hand, draw the next piece, and so on. Once a piece does not fit, place the assembled piece in the left hand down and transfer the new ‘no-fit’ piece from your right to your left hand and contine …

KEY: This assumes the interval list is sorted. If the intervals are not sorted then you need to use set union. This is way faster though.

General Helper Functions