diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 868467a9..9229549e 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,8 @@ +master + - obsplus.utils.stations + * Fixed df_to_inventory to use a local copy of the NRL for compatibility + with ObsPy and NRLv2 (Note that NRLv1 is no longer accessible) + obsplus 0.2.5 - obsplus * Modernized packaging, including src file and pyrpoject.toml (#259) diff --git a/src/obsplus/constants.py b/src/obsplus/constants.py index 4f6c7fde..c2c62c56 100644 --- a/src/obsplus/constants.py +++ b/src/obsplus/constants.py @@ -1,4 +1,5 @@ """Constants used throughout obsplus.""" + from collections import OrderedDict from os import cpu_count from pathlib import Path diff --git a/src/obsplus/exceptions.py b/src/obsplus/exceptions.py index 7acb2133..f59e7fb4 100644 --- a/src/obsplus/exceptions.py +++ b/src/obsplus/exceptions.py @@ -1,6 +1,5 @@ """A collection of ObsPlus Exceptions and Warnings.""" - # --- Exceptions diff --git a/src/obsplus/interfaces.py b/src/obsplus/interfaces.py index dd9e8f0f..e8275e20 100644 --- a/src/obsplus/interfaces.py +++ b/src/obsplus/interfaces.py @@ -4,6 +4,7 @@ Note: These are used instead of the ones in obspy.clients.base so the subclass hooks can be used. """ + from abc import abstractmethod from typing_extensions import Protocol, runtime_checkable diff --git a/src/obsplus/utils/stations.py b/src/obsplus/utils/stations.py index 281ead2b..0e8ce408 100644 --- a/src/obsplus/utils/stations.py +++ b/src/obsplus/utils/stations.py @@ -5,7 +5,7 @@ import warnings from functools import singledispatch, lru_cache from pathlib import Path -from typing import Optional +from typing import Optional, Union import numpy as np import obspy @@ -88,8 +88,9 @@ class _InventoryConstructor: channel=("channel", "location", "start_date", "end_date"), ) - def __init__(self, station_client=None): + def __init__(self, station_client=None, nrl_path=None): self._client = station_client + self._nrl_path = nrl_path def _groupby_if_exists(self, df, level): """Groupby columns if they exist on dataframe, else return empty.""" @@ -136,13 +137,12 @@ def _get_kwargs(self, series, key_mapping): return out - @property @lru_cache() - def nrl_client(self): + def nrl_client(self, path): """Initiate a nominal response library object.""" from obspy.clients.nrl import NRL - return NRL() + return NRL(str(path)) @property @lru_cache() @@ -159,8 +159,8 @@ def station_client(self): return client @lru_cache() - def get_nrl_response(self, datalogger_keys, sensor_keys): - nrl = self.nrl_client + def get_nrl_response(self, path, datalogger_keys, sensor_keys): + nrl = self.nrl_client(path) kwargs = dict(datalogger_keys=datalogger_keys, sensor_keys=sensor_keys) return nrl.get_response(**kwargs) @@ -182,8 +182,12 @@ def _update_nrl_response(self, response, df): # df doesn't have needed columns, just exit logger_keys, sensor_keys = df["datalogger_keys"], df["sensor_keys"] valid = (~logger_keys.isna()) & (~sensor_keys.isna()) + if valid.any() and self._nrl_path is None: + raise AttributeError( + "nrl_path must be specified if using NRL to get instrument responses" + ) response[valid] = [ - self.get_nrl_response(tuple(x), tuple(y)) + self.get_nrl_response(self._nrl_path, tuple(x), tuple(y)) for x, y in zip(logger_keys[valid], sensor_keys[valid]) ] @@ -319,7 +323,9 @@ def _make_inventory(self, df: pd.DataFrame): @compose_docstring(station_columns=station_col_str) def df_to_inventory( - df: pd.DataFrame, client: Optional[StationClient] = None + df: pd.DataFrame, + client: Optional[StationClient] = None, + nrl_path: Optional[Union[Path, str]] = None, ) -> obspy.Inventory: """ Create an inventory from a dataframe. @@ -334,6 +340,10 @@ def df_to_inventory( client Any client with a `get_stations` method. Only used if the dataframe contains special columns for retrieving channel responses. + nrl_path + The path to a local copy of the Nominal Response Library. Only used + if the dataframe contains special columns for retrieving channel + responses. Notes ----- @@ -344,13 +354,16 @@ def df_to_inventory( If the dataframe has columns named "sensor_keys" and "datalogger_keys" these will indicate the response information should be fetched using ObsPy's NRL client. Each of these columns should either contain lists - or josn-loadable strings. + or json-loadable strings. For example, to specify sensor keys: ["Nanometrics", "Trillium 120 Horizon"] or '["Nanometrics", "Trillium 120 Horizon"]' are both valid. + Note that the capability of ObsPy's NRL client to parse the online NRL has + been deprecated and it is now necessary to download and use a local copy. + 2. Using a station client: If the dataframe contains a column get_stations_kwargs it indicates that either a client was passed as the client argument or the fdsn IRIS client @@ -375,7 +388,7 @@ def df_to_inventory( - If both NRL and client methods are indicated by column contents an AmbiguousResponseError will be raised. """ - inv_constructor = _InventoryConstructor(station_client=client) + inv_constructor = _InventoryConstructor(station_client=client, nrl_path=nrl_path) return inv_constructor(df) diff --git a/src/obsplus/version.py b/src/obsplus/version.py index 9255a95e..119ae465 100644 --- a/src/obsplus/version.py +++ b/src/obsplus/version.py @@ -1,4 +1,5 @@ """Module for reporting the package version.""" + from contextlib import suppress from importlib.metadata import PackageNotFoundError, version diff --git a/tests/conftest.py b/tests/conftest.py index c631bdbf..e96d9daf 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -131,6 +131,8 @@ def internet_available(): """Test if internet resources are available.""" import socket + # TODO: This isn't a consistent way to determine if there's internet, especially + # behind a corporate firewall address = "8.8.8.8" port = 53 try: @@ -164,6 +166,12 @@ def load_and_update_dataset(name): has_internet = internet_available() +@pytest.fixture(scope="session") +def data_path(): + """For scenarios when you really just need a path to test data""" + return TEST_DATA_PATH + + # -------------------- collection of test cases diff --git a/tests/test_data/mini_nrl/datalogger/Nanometrics/Centaur.txt b/tests/test_data/mini_nrl/datalogger/Nanometrics/Centaur.txt new file mode 100644 index 00000000..b73eaf23 --- /dev/null +++ b/tests/test_data/mini_nrl/datalogger/Nanometrics/Centaur.txt @@ -0,0 +1,21 @@ +[Main] +question = "What is the full scale voltage?" + +[4Vpp] +path = "Centaur_FV4Vpp.txt" + +[40Vpp] +path = "Centaur_FV40Vpp.txt" + +[2Vpp] +path = "Centaur_FV2Vpp.txt" + +[20Vpp] +path = "Centaur_FV20Vpp.txt" + +[1Vpp] +path = "Centaur_FV1Vpp.txt" + +[10Vpp] +path = "Centaur_FV10Vpp.txt" + diff --git a/tests/test_data/mini_nrl/datalogger/Nanometrics/Centaur_FV1Vpp.txt b/tests/test_data/mini_nrl/datalogger/Nanometrics/Centaur_FV1Vpp.txt new file mode 100644 index 00000000..4c8f12c4 --- /dev/null +++ b/tests/test_data/mini_nrl/datalogger/Nanometrics/Centaur_FV1Vpp.txt @@ -0,0 +1,66 @@ +[Main] +question = "What is the final sample rate?" + +[80 Hz] +path = "Centaur_FV1Vpp_FR80.txt" + + +[5 Hz] +path = "Centaur_FV1Vpp_FR5.txt" + + +[50 Hz] +path = "Centaur_FV1Vpp_FR50.txt" + + +[500 Hz] +path = "Centaur_FV1Vpp_FR500.txt" + + +[5000 Hz] +path = "Centaur_FV1Vpp_FR5000.txt" + + +[40 Hz] +path = "Centaur_FV1Vpp_FR40.txt" + + +[2 Hz] +path = "Centaur_FV1Vpp_FR2.txt" + + +[250 Hz] +path = "Centaur_FV1Vpp_FR250.txt" + + +[20 Hz] +path = "Centaur_FV1Vpp_FR20.txt" + + +[200 Hz] +path = "Centaur_FV1Vpp_FR200.txt" + + +[2000 Hz] +path = "Centaur_FV1Vpp_FR2000.txt" + + +[1 Hz] +path = "Centaur_FV1Vpp_FR1.txt" + + +[125 Hz] +path = "Centaur_FV1Vpp_FR125.txt" + + +[10 Hz] +path = "Centaur_FV1Vpp_FR10.txt" + + +[100 Hz] +path = "Centaur_FV1Vpp_FR100.txt" + + +[1000 Hz] +path = "Centaur_FV1Vpp_FR1000.txt" + diff --git a/tests/test_data/mini_nrl/datalogger/Nanometrics/Centaur_FV1Vpp_FR40.txt b/tests/test_data/mini_nrl/datalogger/Nanometrics/Centaur_FV1Vpp_FR40.txt new file mode 100644 index 00000000..7b697d3a --- /dev/null +++ b/tests/test_data/mini_nrl/datalogger/Nanometrics/Centaur_FV1Vpp_FR40.txt @@ -0,0 +1,10 @@ +[Main] +question = "What is the DC removal/low pass filter setting?" + +[Off] +path = "Centaur_FV1Vpp_FR40_DFOff.txt" + + +[0.001] +path = "Centaur_FV1Vpp_FR40_DF0.001.txt" + diff --git a/tests/test_data/mini_nrl/datalogger/Nanometrics/Centaur_FV1Vpp_FR40_DFOff.txt b/tests/test_data/mini_nrl/datalogger/Nanometrics/Centaur_FV1Vpp_FR40_DFOff.txt new file mode 100644 index 00000000..69188899 --- /dev/null +++ b/tests/test_data/mini_nrl/datalogger/Nanometrics/Centaur_FV1Vpp_FR40_DFOff.txt @@ -0,0 +1,12 @@ +[Main] +question = "What is the final filter phase?" + +[Minimum] +description = "Nanometrics; Centaur; Full-Scale_Voltage 1Vpp; Final_Sample_Rate 40 Hz; DC_Filter Off; Final_Filter_Phase Minimum" +xml = "Centaur_FV1Vpp_FR40_DFOff_FPMinimum.xml" + + +[Linear] +description = "Nanometrics; Centaur; Full-Scale_Voltage 1Vpp; Final_Sample_Rate 40 Hz; DC_Filter Off; Final_Filter_Phase Linear" +xml = "Centaur_FV1Vpp_FR40_DFOff_FPLinear.xml" + diff --git a/tests/test_data/mini_nrl/datalogger/Nanometrics/Centaur_FV1Vpp_FR40_DFOff_FPLinear.xml b/tests/test_data/mini_nrl/datalogger/Nanometrics/Centaur_FV1Vpp_FR40_DFOff_FPLinear.xml new file mode 100644 index 00000000..c60b9c28 --- /dev/null +++ b/tests/test_data/mini_nrl/datalogger/Nanometrics/Centaur_FV1Vpp_FR40_DFOff_FPLinear.xml @@ -0,0 +1,770 @@ + + + IRIS-DMC + IRIS NRL service | version: 1 + https://service.iris.edu/irisws/nrl/1/ + 2023-09-06T01:00:04.261337Z + + + + This is a comment. + + 0.0 + 0.0 + 0.0 + + Long site name + + + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + + The sensor name + + + + +1.60000E+07 + 10 + + V + Volts + + + counts + Digital Counts + + + + + + V + Volts + + + V + Volts + + LAPLACE (RADIANS/SECOND) + 1 + 1 + + + 40 + 1 + + + + + + V + Volts + + + counts + Digital Counts + + DIGITAL + 1.000000e+00 + + + 30000 + 1 + 0 + 0 + 0 + + + 400000 + 0.4 + + + + + + counts + Digital Counts + + + counts + Digital Counts + + DIGITAL + -1.50596e-10 + -1.49886e-10 + -1.00311e-10 + 1.25946e-10 + 7.96045e-10 + 2.42983e-09 + 5.98255e-09 + 1.31276e-08 + 2.66780e-08 + 5.11949e-08 + 9.38368e-08 + 1.65513e-07 + 2.82403e-07 + 4.67904e-07 + 7.55046e-07 + 1.18942e-06 + 1.83258e-06 + 2.76590e-06 + 4.09467e-06 + 5.95238e-06 + 8.50469e-06 + 1.19527e-05 + 1.65353e-05 + 2.25292e-05 + 3.02465e-05 + 4.00291e-05 + 5.22379e-05 + 6.72375e-05 + 8.53738e-05 + 1.06946e-04 + 1.32169e-04 + 1.61134e-04 + 1.93755e-04 + 2.29712e-04 + 2.68398e-04 + 3.08854e-04 + 3.49711e-04 + 3.89140e-04 + 4.24811e-04 + 4.53870e-04 + 4.72936e-04 + 4.78133e-04 + 4.65151e-04 + 4.29345e-04 + 3.65887e-04 + 2.69951e-04 + 1.36952e-04 + -3.71723e-05 + -2.55641e-04 + -5.20481e-04 + -8.32160e-04 + -1.18921e-03 + -1.58785e-03 + -2.02170e-03 + -2.48145e-03 + -2.95468e-03 + -3.42576e-03 + -3.87587e-03 + -4.28310e-03 + -4.62279e-03 + -4.86796e-03 + -4.98988e-03 + -4.95889e-03 + -4.74523e-03 + -4.32010e-03 + -3.65672e-03 + -2.73148e-03 + -1.52512e-03 + -2.38364e-05 + 1.77968e-03 + 3.88537e-03 + 6.28506e-03 + 8.96202e-03 + 1.18907e-02 + 1.50369e-02 + 1.83580e-02 + 2.18039e-02 + 2.53179e-02 + 2.88377e-02 + 3.22978e-02 + 3.56302e-02 + 3.87670e-02 + 4.16424e-02 + 4.41942e-02 + 4.63659e-02 + 4.81089e-02 + 4.93834e-02 + 5.01602e-02 + 5.04211e-02 + 5.01602e-02 + 4.93834e-02 + 4.81089e-02 + 4.63659e-02 + 4.41942e-02 + 4.16424e-02 + 3.87670e-02 + 3.56302e-02 + 3.22978e-02 + 2.88377e-02 + 2.53179e-02 + 2.18039e-02 + 1.83580e-02 + 1.50369e-02 + 1.18907e-02 + 8.96202e-03 + 6.28506e-03 + 3.88537e-03 + 1.77968e-03 + -2.38364e-05 + -1.52512e-03 + -2.73148e-03 + -3.65672e-03 + -4.32010e-03 + -4.74523e-03 + -4.95889e-03 + -4.98988e-03 + -4.86796e-03 + -4.62279e-03 + -4.28310e-03 + -3.87587e-03 + -3.42576e-03 + -2.95468e-03 + -2.48145e-03 + -2.02170e-03 + -1.58785e-03 + -1.18921e-03 + -8.32160e-04 + -5.20481e-04 + -2.55641e-04 + -3.71723e-05 + 1.36952e-04 + 2.69951e-04 + 3.65887e-04 + 4.29345e-04 + 4.65151e-04 + 4.78133e-04 + 4.72936e-04 + 4.53870e-04 + 4.24811e-04 + 3.89140e-04 + 3.49711e-04 + 3.08854e-04 + 2.68398e-04 + 2.29712e-04 + 1.93755e-04 + 1.61134e-04 + 1.32169e-04 + 1.06946e-04 + 8.53738e-05 + 6.72375e-05 + 5.22379e-05 + 4.00291e-05 + 3.02465e-05 + 2.25292e-05 + 1.65353e-05 + 1.19527e-05 + 8.50469e-06 + 5.95238e-06 + 4.09467e-06 + 2.76590e-06 + 1.83258e-06 + 1.18942e-06 + 7.55046e-07 + 4.67904e-07 + 2.82403e-07 + 1.65513e-07 + 9.38368e-08 + 5.11949e-08 + 2.66780e-08 + 1.31276e-08 + 5.98255e-09 + 2.42983e-09 + 7.96045e-10 + 1.25946e-10 + -1.00311e-10 + -1.49886e-10 + -1.50596e-10 + + + 30000 + 15 + 0 + 0.00293333 + 0.00293333 + + + 1 + 0 + + + + + + counts + Digital Counts + + + counts + Digital Counts + + DIGITAL + -1.40023e-08 + -1.25506e-07 + -6.07492e-07 + -2.04687e-06 + -5.23635e-06 + -1.04277e-05 + -1.56651e-05 + -1.46714e-05 + 3.86690e-06 + 5.25492e-05 + 1.34545e-04 + 2.27329e-04 + 2.69409e-04 + 1.65389e-04 + -1.75421e-04 + -7.64991e-04 + -1.45211e-03 + -1.88164e-03 + -1.56238e-03 + -7.93060e-05 + 2.58844e-03 + 5.77767e-03 + 8.07770e-03 + 7.66531e-03 + 3.06602e-03 + -5.85956e-03 + -1.71185e-02 + -2.64597e-02 + -2.82353e-02 + -1.71838e-02 + 9.39470e-03 + 4.99107e-02 + 9.80348e-02 + 1.43940e-01 + 1.76996e-01 + 1.89035e-01 + 1.76996e-01 + 1.43940e-01 + 9.80348e-02 + 4.99107e-02 + 9.39470e-03 + -1.71838e-02 + -2.82353e-02 + -2.64597e-02 + -1.71185e-02 + -5.85956e-03 + 3.06602e-03 + 7.66531e-03 + 8.07770e-03 + 5.77767e-03 + 2.58844e-03 + -7.93060e-05 + -1.56238e-03 + -1.88164e-03 + -1.45211e-03 + -7.64991e-04 + -1.75421e-04 + 1.65389e-04 + 2.69409e-04 + 2.27329e-04 + 1.34545e-04 + 5.25492e-05 + 3.86690e-06 + -1.46714e-05 + -1.56651e-05 + -1.04277e-05 + -5.23635e-06 + -2.04687e-06 + -6.07492e-07 + -1.25506e-07 + -1.40023e-08 + + + 2000 + 5 + 0 + 0.0175 + 0.0175 + + + 1 + 0 + + + + + + counts + Digital Counts + + + counts + Digital Counts + + DIGITAL + 3.62415e-09 + 1.47022e-08 + 2.92465e-08 + 1.67582e-08 + -9.45969e-08 + -4.00529e-07 + -9.37365e-07 + -1.53043e-06 + -1.64599e-06 + -4.07870e-07 + 3.03009e-06 + 8.68599e-06 + 1.47660e-05 + 1.71368e-05 + 1.01281e-05 + -1.07286e-05 + -4.43965e-05 + -8.02980e-05 + -9.76176e-05 + -7.09487e-05 + 1.69209e-05 + 1.58508e-04 + 3.09494e-04 + 3.91280e-04 + 3.15589e-04 + 2.91906e-05 + -4.36272e-04 + -9.35417e-04 + -1.22839e-03 + -1.06147e-03 + -2.93982e-04 + 9.75648e-04 + 2.35245e-03 + 3.21558e-03 + 2.93343e-03 + 1.17105e-03 + -1.82955e-03 + -5.14565e-03 + -7.36121e-03 + -7.05636e-03 + -3.46766e-03 + 2.93511e-03 + 1.02486e-02 + 1.55183e-02 + 1.57062e-02 + 8.98786e-03 + -4.08117e-03 + -2.00454e-02 + -3.30350e-02 + -3.62846e-02 + -2.43088e-02 + 4.95879e-03 + 4.88452e-02 + 1.00015e-01 + 1.48075e-01 + 1.82311e-01 + 1.94711e-01 + 1.82311e-01 + 1.48075e-01 + 1.00015e-01 + 4.88452e-02 + 4.95879e-03 + -2.43088e-02 + -3.62846e-02 + -3.30350e-02 + -2.00454e-02 + -4.08117e-03 + 8.98786e-03 + 1.57062e-02 + 1.55183e-02 + 1.02486e-02 + 2.93511e-03 + -3.46766e-03 + -7.05636e-03 + -7.36121e-03 + -5.14565e-03 + -1.82955e-03 + 1.17105e-03 + 2.93343e-03 + 3.21558e-03 + 2.35245e-03 + 9.75648e-04 + -2.93982e-04 + -1.06147e-03 + -1.22839e-03 + -9.35417e-04 + -4.36272e-04 + 2.91906e-05 + 3.15589e-04 + 3.91280e-04 + 3.09494e-04 + 1.58508e-04 + 1.69209e-05 + -7.09487e-05 + -9.76176e-05 + -8.02980e-05 + -4.43965e-05 + -1.07286e-05 + 1.01281e-05 + 1.71368e-05 + 1.47660e-05 + 8.68599e-06 + 3.03009e-06 + -4.07870e-07 + -1.64599e-06 + -1.53043e-06 + -9.37365e-07 + -4.00529e-07 + -9.45969e-08 + 1.67582e-08 + 2.92465e-08 + 1.47022e-08 + 3.62415e-09 + + + 400 + 5 + 0 + 0.14 + 0.14 + + + 1 + 0 + + + + + + counts + Digital Counts + + + counts + Digital Counts + + DIGITAL + -2.48770e-10 + 4.73744e-09 + 1.24032e-08 + 2.18423e-09 + -2.97350e-08 + -2.77410e-08 + 4.82350e-08 + 9.04852e-08 + -4.37720e-08 + -2.02925e-07 + -2.93251e-08 + 3.57677e-07 + 2.38076e-07 + -5.05054e-07 + -6.56661e-07 + 5.29514e-07 + 1.33303e-06 + -2.35391e-07 + -2.23456e-06 + -6.43189e-07 + 3.17885e-06 + 2.39189e-06 + -3.76643e-06 + -5.21313e-06 + 3.34388e-06 + 9.06984e-06 + -1.03420e-06 + -1.34948e-05 + -4.12820e-06 + 1.74081e-05 + 1.29325e-05 + -1.90112e-05 + -2.55982e-05 + 1.58385e-05 + 4.12985e-05 + -5.05136e-06 + -5.76943e-05 + -1.59734e-05 + 7.06232e-05 + 4.87621e-05 + -7.41183e-05 + -9.26560e-05 + 6.09281e-05 + 1.43704e-04 + -2.36571e-05 + -1.93818e-04 + -4.34607e-05 + 2.30529e-04 + 1.42300e-04 + -2.37697e-04 + -2.68420e-04 + 1.97420e-04 + 4.08986e-04 + -9.32264e-05 + -5.41667e-04 + -8.56506e-05 + 6.35146e-04 + 3.39424e-04 + -6.51794e-04 + -6.53162e-04 + 5.52734e-04 + 9.93533e-04 + -3.05133e-04 + -1.30802e-03 + -1.08987e-04 + 1.52764e-03 + 6.83646e-04 + -1.57381e-03 + -1.38119e-03 + 1.36932e-03 + 2.12784e-03 + -8.52739e-04 + -2.81433e-03 + -5.43598e-06 + 3.30293e-03 + 1.18724e-03 + -3.44149e-03 + -2.61502e-03 + 3.08386e-03 + 4.14554e-03 + -2.11493e-03 + -5.57267e-03 + 4.77543e-04 + 6.64017e-03 + 1.80254e-03 + -7.06464e-03 + -4.59738e-03 + 6.56694e-03 + 7.66690e-03 + -4.90895e-03 + -1.06603e-02 + 1.93106e-03 + 1.31289e-02 + 2.41487e-03 + -1.45476e-02 + -8.04248e-03 + 1.43373e-02 + 1.47221e-02 + -1.18736e-02 + -2.20889e-02 + 6.45106e-03 + 2.96694e-02 + 2.87172e-03 + -3.69222e-02 + -1.77763e-02 + 4.32915e-02 + 4.24836e-02 + -4.82648e-02 + -9.28087e-02 + 5.14286e-02 + 3.13777e-01 + 4.47486e-01 + 3.13777e-01 + 5.14286e-02 + -9.28087e-02 + -4.82648e-02 + 4.24836e-02 + 4.32915e-02 + -1.77763e-02 + -3.69222e-02 + 2.87172e-03 + 2.96694e-02 + 6.45106e-03 + -2.20889e-02 + -1.18736e-02 + 1.47221e-02 + 1.43373e-02 + -8.04248e-03 + -1.45476e-02 + 2.41487e-03 + 1.31289e-02 + 1.93106e-03 + -1.06603e-02 + -4.90895e-03 + 7.66690e-03 + 6.56694e-03 + -4.59738e-03 + -7.06464e-03 + 1.80254e-03 + 6.64017e-03 + 4.77543e-04 + -5.57267e-03 + -2.11493e-03 + 4.14554e-03 + 3.08386e-03 + -2.61502e-03 + -3.44149e-03 + 1.18724e-03 + 3.30293e-03 + -5.43598e-06 + -2.81433e-03 + -8.52739e-04 + 2.12784e-03 + 1.36932e-03 + -1.38119e-03 + -1.57381e-03 + 6.83646e-04 + 1.52764e-03 + -1.08987e-04 + -1.30802e-03 + -3.05133e-04 + 9.93533e-04 + 5.52734e-04 + -6.53162e-04 + -6.51794e-04 + 3.39424e-04 + 6.35146e-04 + -8.56506e-05 + -5.41667e-04 + -9.32264e-05 + 4.08986e-04 + 1.97420e-04 + -2.68420e-04 + -2.37697e-04 + 1.42300e-04 + 2.30529e-04 + -4.34607e-05 + -1.93818e-04 + -2.36571e-05 + 1.43704e-04 + 6.09281e-05 + -9.26560e-05 + -7.41183e-05 + 4.87621e-05 + 7.06232e-05 + -1.59734e-05 + -5.76943e-05 + -5.05136e-06 + 4.12985e-05 + 1.58385e-05 + -2.55982e-05 + -1.90112e-05 + 1.29325e-05 + 1.74081e-05 + -4.12820e-06 + -1.34948e-05 + -1.03420e-06 + 9.06984e-06 + 3.34388e-06 + -5.21313e-06 + -3.76643e-06 + 2.39189e-06 + 3.17885e-06 + -6.43189e-07 + -2.23456e-06 + -2.35391e-07 + 1.33303e-06 + 5.29514e-07 + -6.56661e-07 + -5.05054e-07 + 2.38076e-07 + 3.57677e-07 + -2.93251e-08 + -2.02925e-07 + -4.37720e-08 + 9.04852e-08 + 4.82350e-08 + -2.77410e-08 + -2.97350e-08 + 2.18423e-09 + 1.24032e-08 + 4.73744e-09 + -2.48770e-10 + + + 80 + 2 + 0 + 1.3875 + 1.3875 + + + 1 + 0 + + + + + + + + diff --git a/tests/test_data/mini_nrl/datalogger/Nanometrics/index.txt b/tests/test_data/mini_nrl/datalogger/Nanometrics/index.txt new file mode 100644 index 00000000..ded05592 --- /dev/null +++ b/tests/test_data/mini_nrl/datalogger/Nanometrics/index.txt @@ -0,0 +1,42 @@ +[Main] +question = "Select the Nanometrics datalogger model" + +[Trident] +path="Trident.txt" + +[Trident305] +path="Trident305.txt" + +[TitanSMA] +path="TitanSMA.txt" + +[TitanEA] +path="TitanEA.txt" + +[Taurus] +path="Taurus.txt" + +[Pegasus] +path="Pegasus.txt" + +[Orion] +path="Orion.txt" + +[MeridianPosthole] +path="MeridianPosthole.txt" + +[MeridianCompact] +path="MeridianCompact.txt" + +[HRD-24] +path="HRD-24.txt" + +[EuropaT] +path="EuropaT.txt" + +[Centaur] +path="Centaur.txt" + +[CentaurHighGain] +path="CentaurHighGain.txt" + diff --git a/tests/test_data/mini_nrl/datalogger/index.txt b/tests/test_data/mini_nrl/datalogger/index.txt new file mode 100644 index 00000000..4b518340 --- /dev/null +++ b/tests/test_data/mini_nrl/datalogger/index.txt @@ -0,0 +1,87 @@ +[Main] +question = "Select the datalogger manufacturer" + +[WorldSensing] +path="WorldSensing/index.txt" + +[SolGeo] +path="SolGeo/index.txt" + +[Sercel] +path="Sercel/index.txt" + +[SeismologyResearchCentre] +path="SeismologyResearchCentre/index.txt" + +[SeismicSource] +path="SeismicSource/index.txt" + +[STANEO] +path="STANEO/index.txt" + +[SARA] +path="SARA/index.txt" + +[RSensors] +path="RSensors/index.txt" + +[REFTEK] +path="REFTEK/index.txt" + +[Quanterra] +path="Quanterra/index.txt" + +[Nanometrics] +path="Nanometrics/index.txt" + +[MagseisFairfield] +path="MagseisFairfield/index.txt" + +[Lunitek] +path="Lunitek/index.txt" + +[Kinemetrics] +path="Kinemetrics/index.txt" + +[Guralp] +path="Guralp/index.txt" + +[Geotech] +path="Geotech/index.txt" + +[GeoSIG] +path="GeoSIG/index.txt" + +[GeoDevice] +path="GeoDevice/index.txt" + +[GenericUnity] +path="GenericUnity/index.txt" + +[GEObit] +path="GEObit/index.txt" + +[Eentec] +path="Eentec/index.txt" + +[EarthData] +path="EarthData/index.txt" + +[EQMet] +path="EQMet/index.txt" + +[DiGOSOmnirecs] +path="DiGOSOmnirecs/index.txt" + +[DTCC] +path="DTCC/index.txt" + +[DAQSystems] +path="DAQSystems/index.txt" + +[CNSN] +path="CNSN/index.txt" + +[Agecodagis] +path="Agecodagis/index.txt" + diff --git a/tests/test_data/mini_nrl/index.txt b/tests/test_data/mini_nrl/index.txt new file mode 100644 index 00000000..353471e8 --- /dev/null +++ b/tests/test_data/mini_nrl/index.txt @@ -0,0 +1,15 @@ +[Main] +question = "Select the hardware element" + +[Soh] +path = "soh/index.txt" + +[Sensor] +path = "sensor/index.txt" + +[Integrated] +path = "integrated/index.txt" + +[Datalogger] +path = "datalogger/index.txt" + diff --git a/tests/test_data/mini_nrl/sensor/Nanometrics/TrilliumHorizon120.txt b/tests/test_data/mini_nrl/sensor/Nanometrics/TrilliumHorizon120.txt new file mode 100644 index 00000000..d26cbaf5 --- /dev/null +++ b/tests/test_data/mini_nrl/sensor/Nanometrics/TrilliumHorizon120.txt @@ -0,0 +1,7 @@ +[Main] +question = "What is the long-period corner?" + +[120 s] +description = "Nanometrics; TrilliumHorizon120; Long-Period_Corner 120 s; Sensitivity 1203 V/m/s; Sensor_Type groundVel" +xml = "TrilliumHorizon120_LP120_SG1203_STgroundVel.xml" + diff --git a/tests/test_data/mini_nrl/sensor/Nanometrics/TrilliumHorizon120_LP120_SG1203_STgroundVel.xml b/tests/test_data/mini_nrl/sensor/Nanometrics/TrilliumHorizon120_LP120_SG1203_STgroundVel.xml new file mode 100644 index 00000000..799fa128 --- /dev/null +++ b/tests/test_data/mini_nrl/sensor/Nanometrics/TrilliumHorizon120_LP120_SG1203_STgroundVel.xml @@ -0,0 +1,133 @@ + + + IRIS-DMC + IRIS NRL service | version: 1 + https://service.iris.edu/irisws/nrl/1/ + 2023-09-06T01:00:04.261337Z + + + + This is a comment. + + 0.0 + 0.0 + 0.0 + + Long site name + + + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + + The sensor name + + + + +1.20250E+03 + 1 + + m/s + Velocity in Meters Per Second + + + V + Volts + + + + + + m/s + Velocity in Meters Per Second + + + V + Volts + + LAPLACE (RADIANS/SECOND) + 8.31871e+17 + 1 + + 0 + 0 + + + 0 + 0 + + + -31.63 + 0 + + + -160 + 0 + + + -350 + 0 + + + -3177 + 0 + + + -0.036614 + -0.037059 + + + -0.036614 + 0.037059 + + + -32.55 + 0 + + + -142 + 0 + + + -364 + -404 + + + -364 + 404 + + + -1260 + 0 + + + -4900 + -5200 + + + -4900 + 5200 + + + -7100 + -1700 + + + -7100 + 1700 + + + + 1202.5 + 1 + + + + + + + + diff --git a/tests/test_data/mini_nrl/sensor/Nanometrics/index.txt b/tests/test_data/mini_nrl/sensor/Nanometrics/index.txt new file mode 100644 index 00000000..a16eae8b --- /dev/null +++ b/tests/test_data/mini_nrl/sensor/Nanometrics/index.txt @@ -0,0 +1,93 @@ +[Main] +question = "Select the Nanometrics sensor model" + +[TrilliumSlimPosthole120] +path="TrilliumSlimPosthole120.txt" + +[TrilliumHorizon120v2] +path="TrilliumHorizon120v2.txt" + +[TrilliumHorizon120] +path="TrilliumHorizon120.txt" + +[TrilliumCompact20] +path="TrilliumCompact20.txt" + +[TrilliumCompact20PH] +path="TrilliumCompact20PH.txt" + +[TrilliumCompact20Horizon] +path="TrilliumCompact20Horizon.txt" + +[TrilliumCompact120] +path="TrilliumCompact120.txt" + +[TrilliumCompact120PH] +path="TrilliumCompact120PH.txt" + +[TrilliumCompact120OBS] +path="TrilliumCompact120OBS.txt" + +[TrilliumCompact120Horizon] +path="TrilliumCompact120Horizon.txt" + +[TrilliumCascadia] +path="TrilliumCascadia.txt" + +[TrilliumAllTerrain] +path="TrilliumAllTerrain.txt" + +[Trillium40] +path="Trillium40.txt" + +[Trillium360] +path="Trillium360.txt" + +[Trillium360PH] +path="Trillium360PH.txt" + +[Trillium360GSN] +path="Trillium360GSN.txt" + +[Trillium360GSNPH] +path="Trillium360GSNPH.txt" + +[Trillium360GSNBH] +path="Trillium360GSNBH.txt" + +[Trillium360BH] +path="Trillium360BH.txt" + +[Trillium240] +path="Trillium240.txt" + +[Trillium240OBS] +path="Trillium240OBS.txt" + +[Trillium120Q] +path="Trillium120Q.txt" + +[Trillium120QA] +path="Trillium120QA.txt" + +[Trillium120P] +path="Trillium120P.txt" + +[Trillium120PH] +path="Trillium120PH.txt" + +[Trillium120PA] +path="Trillium120PA.txt" + +[Trillium120BH] +path="Trillium120BH.txt" + +[Titan] +path="Titan.txt" + +[MeridianPosthole] +path="MeridianPosthole.txt" + +[MeridianCompactPosthole] +path="MeridianCompactPosthole.txt" + diff --git a/tests/test_data/mini_nrl/sensor/index.txt b/tests/test_data/mini_nrl/sensor/index.txt new file mode 100644 index 00000000..a880bf0e --- /dev/null +++ b/tests/test_data/mini_nrl/sensor/index.txt @@ -0,0 +1,117 @@ +[Main] +question = "Select the sensor manufacturer" + +[iTem] +path="iTem/index.txt" + +[Sunfull] +path="Sunfull/index.txt" + +[Streckeisen] +path="Streckeisen/index.txt" + +[Sprengnether] +path="Sprengnether/index.txt" + +[SolGeo] +path="SolGeo/index.txt" + +[SiliconAudio] +path="SiliconAudio/index.txt" + +[Sercel] +path="Sercel/index.txt" + +[SensorNederland] +path="SensorNederland/index.txt" + +[SeismoWave] +path="SeismoWave/index.txt" + +[SARA] +path="SARA/index.txt" + +[RTClark] +path="RTClark/index.txt" + +[RSensors] +path="RSensors/index.txt" + +[REFTEK] +path="REFTEK/index.txt" + +[Nanometrics] +path="Nanometrics/index.txt" + +[MagseisFairfield] +path="MagseisFairfield/index.txt" + +[Lunitek] +path="Lunitek/index.txt" + +[Lennartz] +path="Lennartz/index.txt" + +[LaHusen] +path="LaHusen/index.txt" + +[Kinemetrics] +path="Kinemetrics/index.txt" + +[JeffreyBJohnson] +path="JeffreyBJohnson/index.txt" + +[IESE] +path="IESE/index.txt" + +[Hyperion] +path="Hyperion/index.txt" + +[HighTech] +path="HighTech/index.txt" + +[HGSProducts] +path="HGSProducts/index.txt" + +[Guralp] +path="Guralp/index.txt" + +[Geotech] +path="Geotech/index.txt" + +[GeoSpace] +path="GeoSpace/index.txt" + +[GeoSIG] +path="GeoSIG/index.txt" + +[GeoDevice] +path="GeoDevice/index.txt" + +[GenericUnity] +path="GenericUnity/index.txt" + +[GaiaCode] +path="GaiaCode/index.txt" + +[GEObit] +path="GEObit/index.txt" + +[Eentec] +path="Eentec/index.txt" + +[EQMet] +path="EQMet/index.txt" + +[DTCC] +path="DTCC/index.txt" + +[Chaparral] +path="Chaparral/index.txt" + +[CEADASE] +path="CEADASE/index.txt" + +[ASIR] +path="ASIR/index.txt" + diff --git a/tests/test_utils/test_stations_utils.py b/tests/test_utils/test_stations_utils.py index cedf609a..eab605ff 100644 --- a/tests/test_utils/test_stations_utils.py +++ b/tests/test_utils/test_stations_utils.py @@ -2,6 +2,7 @@ Tests for station utilities. """ import os +from pathlib import Path import numpy as np @@ -207,6 +208,11 @@ def test_unsupported_column_warns(self, df_from_inv): class TestDfToInventoryGetResponses: """Tests for getting responses with the df_to_inventory function.""" + @pytest.fixture(scope="class") + def mini_NRL(self, data_path): + """Return a path to a miniaturized NRL for df_to_inventory tests""" + return Path(data_path) / "mini_nrl" + def has_valid_response(self, inventory, expected_missing=None): """ Return True if the inventory has expected responses. @@ -239,15 +245,15 @@ def df_with_nrl_response(self): df = obsplus.stations_to_df(inv) # set instrument str - sensor_keys = ("Nanometrics", "Trillium 120 Horizon", "Trillium 120 Horizon") + sensor_keys = ("Nanometrics", "TrilliumHorizon120", "120 s") # get digitizer keys datalogger_keys = ( "Nanometrics", "Centaur", - "1 Vpp (40)", + "1Vpp", + "40 Hz", "Off", - "Linear phase", - "100", + "Linear", ) # keep one as a tuple and convert the other to str df["sensor_keys"] = [sensor_keys for _ in range(len(df))] @@ -327,22 +333,27 @@ def df_ambiguous_client_query(self, df_with_get_stations_kwargs): df.loc[1, "get_station_kwargs"]["channel"] = "*" return df - def test_nrl_responses(self, df_with_nrl_response): + def test_nrl_responses(self, df_with_nrl_response, mini_NRL): """Ensure the NRL is used to pull responses.""" with suppress_warnings(): - inv = df_to_inventory(df_with_nrl_response) + inv = df_to_inventory(df_with_nrl_response, nrl_path=mini_NRL) assert self.has_valid_response(inv) - def test_response_one_missing(self, df_with_partial_responses): + def test_response_one_missing(self, df_with_partial_responses, mini_NRL): """Ensure responses which can be got are fetched.""" df = df_with_partial_responses with suppress_warnings(): - inv = df_to_inventory(df) + inv = df_to_inventory(df, nrl_path=mini_NRL) missing = df["sensor_keys"].isnull() | df["datalogger_keys"].isnull() missing_seed_ids = set(get_seed_id_series(df[missing])) assert self.has_valid_response(inv, missing_seed_ids) + def test_nrl_path_not_provided(self, df_with_nrl_response): + """Ensure raise expectedly if no NRL library path specified""" + with pytest.raises(AttributeError, match="nrl_path"): + df_to_inventory(df_with_nrl_response) + def test_get_stations_client(self, df_with_get_stations_kwargs): """Ensure get_station_kwargs results responses.""" if os.environ.get("CI", False):