diff --git a/docs/elements.md b/docs/elements.md index ff68b4c9aaab31d8ec85be936ef15f0947801157..d4340c308c55d41c0caed68645d75983e2d853dc 100644 --- a/docs/elements.md +++ b/docs/elements.md @@ -19,7 +19,7 @@ Elements generated by observatories running the Obsrio data acquisition system. - U, V, W - uses instrument metadata from `geomagio.metadata.instrument.InstrumentCalibrations.get_instrument_calibrations` to convert volt+bin to engineering units. + uses instrument metadata from `geomagio.Metadata.get_instrument` to convert volt+bin to engineering units. uses `geomagio.algorithm.FilterAlgorithm` to filter from 10Hz to 1Hz. diff --git a/geomagio/Metadata.py b/geomagio/Metadata.py new file mode 100644 index 0000000000000000000000000000000000000000..ebdb7b8c19e1033acceb5213cf0640ec2edcf315 --- /dev/null +++ b/geomagio/Metadata.py @@ -0,0 +1,1363 @@ +"""Simulate metadata service until it is implemented. +""" + +from obspy import UTCDateTime + + +def get_instrument(observatory, start_time=None, end_time=None, metadata=None): + """Get instrument metadata + + Args: + observatory: observatory code + start_time: start time to match, or None to match any. + end_time: end time to match, or None to match any. + metadata: use custom list, defaults to _INSTRUMENT_METADATA + Returns: + list of matching metadata + """ + metadata = metadata or _INSTRUMENT_METADATA + return [ + m + for m in metadata + if m["station"] == observatory + and (end_time is None or m["start_time"] is None or m["start_time"] < end_time) + and (start_time is None or m["end_time"] is None or m["end_time"] > start_time) + ] + + +""" +To make this list easier to maintain: + - List NT network stations first, then other networks in alphabetical order + - Within networks, alphabetize by station, then start_time. + - When updating a metadata object, copy/paste the current one to the end of the list and update the endtime appropriately. + - Then update the existing object with the new information. +""" +_INSTRUMENT_METADATA = [ + { + "network": "NT", + "station": "BDT", + "start_time": None, + "end_time": UTCDateTime("2023-09-22T00:00:00.000Z"), + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 20613, "scale": 966.7624}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 944.1253}], + "W": [{"channel": "W_Volt", "offset": 47450, "scale": 975.5875}], + }, + "electronics": { + "serial": "E574", + # these scale values are calculated manually. + "x-scale": 966.7624, # nT/V + "y-scale": 944.1253, # nT/V + "z-scale": 975.5875, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0449", + # these constants combine with instrument setting for offset + "x-constant": 37027, # nT/mA + "y-constant": 36160, # nT/mA + "z-constant": 37365, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "BDT", + "start_time": UTCDateTime("2023-09-22T00:00:00.000Z"), + "end_time": UTCDateTime("2024-03-07T00:00:00.000Z"), + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 20729.5, "scale": 966.7624}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 944.1253}], + "W": [{"channel": "W_Volt", "offset": 47042.5, "scale": 975.5875}], + }, + "electronics": { + "serial": "E574", + # these scale values are calculated manually. + "x-scale": 966.7624, # nT/V + "y-scale": 944.1253, # nT/V + "z-scale": 975.5875, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0449", + # these constants combine with instrument setting for offset + "x-constant": 37027, # nT/mA + "y-constant": 36160, # nT/mA + "z-constant": 37365, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "BDT", + "start_time": UTCDateTime("2024-03-07T00:00:00.000Z"), + "end_time": None, + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 20724.67, "scale": 966.7624}], + "V": [{"channel": "V_Volt", "offset": -13.59, "scale": 944.1253}], + "W": [{"channel": "W_Volt", "offset": 47048.96, "scale": 975.5875}], + }, + "electronics": { + "serial": "E574", + # these scale values are calculated manually. + "x-scale": 966.7624, # nT/V + "y-scale": 944.1253, # nT/V + "z-scale": 975.5875, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0449", + # these constants combine with instrument setting for offset + "x-constant": 37027, # nT/mA + "y-constant": 36160, # nT/mA + "z-constant": 37365, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "BOU", + "start_time": None, + "end_time": None, + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 100}, + {"channel": "U_Bin", "offset": 0, "scale": 500}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 100}, + {"channel": "V_Bin", "offset": 0, "scale": 500}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100}, + {"channel": "W_Bin", "offset": 0, "scale": 500}, + ], + }, + }, + }, + { + "network": "NT", + "station": "BXX", + "start_time": None, + "end_time": None, + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 100}, + {"channel": "U_Bin", "offset": 0, "scale": 500}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 100}, + {"channel": "V_Bin", "offset": 0, "scale": 500}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100}, + {"channel": "W_Bin", "offset": 0, "scale": 500}, + ], + }, + }, + }, + { + "network": "NT", + "station": "BRT", + "start_time": None, + "end_time": None, + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 100}, + {"channel": "U_Bin", "offset": 0, "scale": 506}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 100}, + {"channel": "V_Bin", "offset": 0, "scale": 505.6}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100}, + {"channel": "W_Bin", "offset": 0, "scale": 506}, + ], + }, + }, + }, + { + "network": "NT", + "station": "BRW", + "start_time": UTCDateTime("2023-10-24T22:45:00.000Z"), + "end_time": None, + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 9214, "scale": 5797.3}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 5777.6}], + "W": [{"channel": "W_Volt", "offset": 37172, "scale": 5895.6}], + }, + "electronics": { + "serial": "????", + # these scale values are calculated manually. + "x-scale": 5797.3, # nT/V + "y-scale": 5777.6, # nT/V + "z-scale": 5895.6, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "????", + # these constants combine with instrument setting for offset + "x-constant": None, # nT/mA + "y-constant": None, # nT/mA + "z-constant": None, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "BSL", + "start_time": None, + "end_time": None, + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 100}, + {"channel": "U_Bin", "offset": 0, "scale": 500}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 100}, + {"channel": "V_Bin", "offset": 0, "scale": 500}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100}, + {"channel": "W_Bin", "offset": 0, "scale": 500}, + ], + }, + }, + }, + { + "network": "NT", + "station": "CMO", + "start_time": UTCDateTime("2023-10-27T16:20:00.000Z"), + "end_time": None, + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 12620, "scale": 967.7}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 969.7}], + "W": [{"channel": "W_Volt", "offset": 54907, "scale": 973.4}], + }, + "electronics": { + "serial": "E0568", + # these scale values are used to convert voltage + "x-scale": 967.7, # nT/V + "y-scale": 969.7, # nT/V + "z-scale": 973.4, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0443", + # these constants combine with instrument setting for offset + "x-constant": 37062, # nT/mA + "y-constant": 37141, # nT/mA + "z-constant": 37281, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "CMT", + "start_time": UTCDateTime("2023-10-26T21:00:00.000Z"), + "end_time": None, + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 99.4}, + {"channel": "U_Bin", "offset": 0, "scale": 502.5}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 101.5}, + {"channel": "V_Bin", "offset": 0, "scale": 512.5}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100.98}, + {"channel": "W_Bin", "offset": 0, "scale": 509.15}, + ], + }, + }, + }, + { + "network": "NT", + "station": "DED", + "start_time": None, + "end_time": None, + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 100}, + {"channel": "U_Bin", "offset": 0, "scale": 508.20}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 100}, + {"channel": "V_Bin", "offset": 0, "scale": 508.40}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100}, + {"channel": "W_Bin", "offset": 0, "scale": 508.03}, + ], + }, + }, + }, + { + "network": "NT", + "station": "FDT", + "start_time": None, + "end_time": None, + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 100}, + {"channel": "U_Bin", "offset": 0, "scale": 500}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 100}, + {"channel": "V_Bin", "offset": 0, "scale": 500}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100}, + {"channel": "W_Bin", "offset": 0, "scale": 500}, + ], + }, + }, + }, + { + "network": "NT", + "station": "FRD", + "start_time": None, + "end_time": UTCDateTime("2023-08-23T00:00:00.000Z"), + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 100}, + {"channel": "U_Bin", "offset": 0, "scale": 500}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 100}, + {"channel": "V_Bin", "offset": 0, "scale": 500}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100}, + {"channel": "W_Bin", "offset": 0, "scale": 500}, + ], + }, + }, + }, + { + "network": "NT", + "station": "FRD", + "start_time": UTCDateTime("2023-08-23T00:00:00.000Z"), + "end_time": UTCDateTime("2023-08-30T00:00:00.000Z"), + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 21639, "scale": 978.4}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 971.0}], + "W": [{"channel": "W_Volt", "offset": 45573, "scale": 966.7}], + }, + "electronics": { + "serial": "E570", + # these scale values are used to convert voltage + "x-scale": 978.4, # nT/V + "y-scale": 971.0, # nT/V + "z-scale": 966.7, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0445", + # these constants combine with instrument setting for offset + "x-constant": 37474, # nT/mA + "y-constant": 37191, # nT/mA + "z-constant": 37025, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "FRD", + "start_time": UTCDateTime("2023-08-30T00:00:00.000Z"), + "end_time": None, + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 21639, "scale": 978.4}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 971.0}], + "W": [{"channel": "W_Volt", "offset": 45573, "scale": 966.7}], + }, + "electronics": { + "serial": "E570", + # these scale values are used to convert voltage + "x-scale": 978.4, # nT/V + "y-scale": 971.0, # nT/V + "z-scale": 966.7, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0445", + # these constants combine with instrument setting for offset + "x-constant": 37474, # nT/mA + "y-constant": 37191, # nT/mA + "z-constant": 37025, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "FRN", + "start_time": None, + "end_time": None, + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 98.48}, + {"channel": "U_Bin", "offset": 0, "scale": 497.50}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 100.60}, + {"channel": "V_Bin", "offset": 0, "scale": 506}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 99}, + {"channel": "W_Bin", "offset": 0, "scale": 501}, + ], + }, + }, + }, + { + "network": "NT", + "station": "GUA", + "start_time": None, + "end_time": UTCDateTime("2024-02-26T03:00:00.000Z"), + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 100}, + {"channel": "U_Bin", "offset": 0, "scale": 500}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 100}, + {"channel": "V_Bin", "offset": 0, "scale": 500}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100}, + {"channel": "W_Bin", "offset": 0, "scale": 500}, + ], + }, + }, + }, + { + "network": "NT", + "station": "GUA", + "start_time": UTCDateTime("2024-02-26T03:00:00.000Z"), + "end_time": UTCDateTime("2024-03-07T00:00:00.000Z"), + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 35975, "scale": 314.28}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 310.48}], + "W": [{"channel": "W_Volt", "offset": 7750, "scale": 317.5}], + }, + "electronics": { + "serial": "E0542", + # these scale values are used to convert voltage + "x-scale": 314.28, # V/nT + "y-scale": 310.48, # V/nT + "z-scale": 317.5, # V/nT + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0420", + # these constants combine with instrument setting for offset + "x-constant": 37085, # nT/mA + "y-constant": 36637, # nT/mA + "z-constant": 37465, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "GUA", + "start_time": UTCDateTime("2024-03-07T00:00:00.000Z"), + "end_time": None, + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 35976, "scale": 314.28}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 310.48}], + "W": [{"channel": "W_Volt", "offset": 7745, "scale": 317.5}], + }, + "electronics": { + "serial": "E0542", + # these scale values are used to convert voltage + "x-scale": 314.28, # V/nT + "y-scale": 310.48, # V/nT + "z-scale": 317.5, # V/nT + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0420", + # these constants combine with instrument setting for offset + "x-constant": 37085, # nT/mA + "y-constant": 36637, # nT/mA + "z-constant": 37465, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "GUT", + "start_time": None, + "end_time": UTCDateTime("2023-09-22T00:00:00.000Z"), + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 35989, "scale": 314.28}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 310.48}], + "W": [{"channel": "W_Volt", "offset": 7654, "scale": 317.5}], + }, + "electronics": { + "serial": "E0542", + # these scale values are used to convert voltage + "x-scale": 314.28, # V/nT + "y-scale": 310.48, # V/nT + "z-scale": 317.5, # V/nT + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0420", + # these constants combine with instrument setting for offset + "x-constant": 37085, # nT/mA + "y-constant": 36637, # nT/mA + "z-constant": 37465, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "GUT", + "start_time": UTCDateTime("2023-09-22T00:00:00.000Z"), + "end_time": UTCDateTime("2024-02-26T03:00:00.000Z"), + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 35975, "scale": 314.28}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 310.48}], + "W": [{"channel": "W_Volt", "offset": 7750, "scale": 317.5}], + }, + "electronics": { + "serial": "E0542", + # these scale values are used to convert voltage + "x-scale": 314.28, # V/nT + "y-scale": 310.48, # V/nT + "z-scale": 317.5, # V/nT + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0420", + # these constants combine with instrument setting for offset + "x-constant": 37085, # nT/mA + "y-constant": 36637, # nT/mA + "z-constant": 37465, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "GUT", + "start_time": UTCDateTime("2024-02-26T03:00:00.000Z"), + "end_time": None, + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 100}, + {"channel": "U_Bin", "offset": 0, "scale": 500}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 100}, + {"channel": "V_Bin", "offset": 0, "scale": 500}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100}, + {"channel": "W_Bin", "offset": 0, "scale": 500}, + ], + }, + }, + }, + { + "network": "NT", + "station": "HON", + "start_time": None, + "end_time": UTCDateTime("2024-02-20T20:30:00.000Z"), + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 100}, + {"channel": "U_Bin", "offset": 0, "scale": 500}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 100}, + {"channel": "V_Bin", "offset": 0, "scale": 500}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100}, + {"channel": "W_Bin", "offset": 0, "scale": 500}, + ], + }, + }, + }, + { + "network": "NT", + "station": "HON", + "start_time": UTCDateTime("2024-02-20T20:30:00.000Z"), + "end_time": UTCDateTime("2024-03-07T00:00:00.000Z"), + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 27126, "scale": 315.4}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 315.0}], + "W": [{"channel": "W_Volt", "offset": 21107.5, "scale": 311.7}], + }, + # this info should get updated when available + "electronics": { + "serial": "E558", + # these scale values are used to convert voltage + # these are calculated using Ohm's law, given scaling resistor value, and given nT/mA values. + "x-scale": 315.4, # nT/V + "y-scale": 315.0, # nT/V + "z-scale": 311.7, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0428", + # these constants combine with instrument setting for offset + "x-constant": 37220, # nT/mA + "y-constant": 37175, # nT/mA + "z-constant": 36775, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "HON", + "start_time": UTCDateTime("2024-03-07T00:00:00.000Z"), + "end_time": None, + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 27126, "scale": 315.4}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 315.0}], + "W": [{"channel": "W_Volt", "offset": 21207.5, "scale": 311.7}], + }, + # this info should get updated when available + "electronics": { + "serial": "E558", + # these scale values are used to convert voltage + # these are calculated using Ohm's law, given scaling resistor value, and given nT/mA values. + "x-scale": 315.4, # nT/V + "y-scale": 315.0, # nT/V + "z-scale": 311.7, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0428", + # these constants combine with instrument setting for offset + "x-constant": 37220, # nT/mA + "y-constant": 37175, # nT/mA + "z-constant": 36775, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "HOT", + "start_time": None, + "end_time": UTCDateTime("2022-07-14T16:07:30.000Z"), + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 0, "scale": 971.8}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 970.6}], + "W": [{"channel": "W_Volt", "offset": 0, "scale": 960.2}], + }, + # this info should get updated when available + "electronics": { + "serial": "E558", + # these scale values are used to convert voltage + # these are calculated using Ohm's law, given scaling resistor value, and given nT/mA values. + "x-scale": 971.8, # nT/V + "y-scale": 970.6, # nT/V + "z-scale": 960.2, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0428", + # these constants combine with instrument setting for offset + "x-constant": 37220, # nT/mA + "y-constant": 37175, # nT/mA + "z-constant": 36775, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "HOT", + "start_time": UTCDateTime("2022-07-14T16:07:30.000Z"), + "end_time": UTCDateTime("2023-09-22T00:00:00.000Z"), + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 27123, "scale": 315.4}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 315.0}], + "W": [{"channel": "W_Volt", "offset": 21158, "scale": 311.7}], + }, + # this info should get updated when available + "electronics": { + "serial": "E558", + # these scale values are used to convert voltage + # these are calculated using Ohm's law, given scaling resistor value, and given nT/mA values. + "x-scale": 315.4, # nT/V + "y-scale": 315.0, # nT/V + "z-scale": 311.7, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0428", + # these constants combine with instrument setting for offset + "x-constant": 37220, # nT/mA + "y-constant": 37175, # nT/mA + "z-constant": 36775, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "HOT", + "start_time": UTCDateTime("2023-09-22T00:00:00.000Z"), + "end_time": UTCDateTime("2024-02-20T20:30:00.000Z"), + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 27126, "scale": 315.4}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 315.0}], + "W": [{"channel": "W_Volt", "offset": 21107.5, "scale": 311.7}], + }, + # this info should get updated when available + "electronics": { + "serial": "E558", + # these scale values are used to convert voltage + # these are calculated using Ohm's law, given scaling resistor value, and given nT/mA values. + "x-scale": 315.4, # nT/V + "y-scale": 315.0, # nT/V + "z-scale": 311.7, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0428", + # these constants combine with instrument setting for offset + "x-constant": 37220, # nT/mA + "y-constant": 37175, # nT/mA + "z-constant": 36775, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "HOT", + "start_time": UTCDateTime("2024-02-20T20:30:00.000Z"), + "end_time": None, + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 100}, + {"channel": "U_Bin", "offset": 0, "scale": 500}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 100}, + {"channel": "V_Bin", "offset": 0, "scale": 500}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100}, + {"channel": "W_Bin", "offset": 0, "scale": 500}, + ], + }, + }, + }, + { + "network": "NT", + "station": "NEW", + "start_time": None, + "end_time": None, + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 100}, + {"channel": "U_Bin", "offset": 0, "scale": 500}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 100}, + {"channel": "V_Bin", "offset": 0, "scale": 500}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100}, + {"channel": "W_Bin", "offset": 0, "scale": 500}, + ], + }, + }, + }, + { + "network": "NT", + "station": "LLO", + "start_time": None, + "end_time": None, + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 100}, + {"channel": "U_Bin", "offset": 0, "scale": 500}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 100}, + {"channel": "V_Bin", "offset": 0, "scale": 500}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100}, + {"channel": "W_Bin", "offset": 0, "scale": 500}, + ], + }, + }, + }, + { + "network": "NT", + "station": "SHU", + "start_time": None, + "end_time": UTCDateTime("2023-06-28T00:00:00.000Z"), + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 100}, + {"channel": "U_Bin", "offset": 0, "scale": 505}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 100}, + {"channel": "V_Bin", "offset": 0, "scale": 505}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100}, + {"channel": "W_Bin", "offset": 0, "scale": 505}, + ], + }, + }, + }, + { + "network": "NT", + "station": "SHU", + "start_time": UTCDateTime("2023-06-28T00:00:00.000Z"), + "end_time": UTCDateTime("2023-09-07T00:00:00.000Z"), + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 19710, "scale": 944.935}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 964.909}], + "W": [{"channel": "W_Volt", "offset": 48068, "scale": 966.893}], + }, + # this info should get updated when available + "electronics": { + "serial": "E566", + # these scale values are used to convert voltage + # these are calculated using Ohm's law, given scaling resistor value (38.3 kohm), and given nT/mA values. + "x-scale": 944.935, # nT/V + "y-scale": 964.909, # nT/V + "z-scale": 966.893, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0441", + # these constants combine with instrument setting for offset + "x-constant": 36191, # nT/mA + "y-constant": 36956, # nT/mA + "z-constant": 37032, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "SHU", + "start_time": UTCDateTime("2023-09-07T00:00:00.000Z"), + "end_time": None, + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 19710, "scale": 975.1}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 969.4}], + "W": [{"channel": "W_Volt", "offset": 48068, "scale": 978.5}], + }, + # this info should get updated when available + "electronics": { + "serial": "E0598", + # these scale values are used to convert voltage + "x-scale": 975.1, # nT/V + "y-scale": 969.4, # nT/V + "z-scale": 978.5, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0460", + "x-constant": 37348, # nT/mA + "y-constant": 37127, # nT/mA + "z-constant": 37477, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "SIT", + "start_time": None, + "end_time": None, + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 100}, + {"channel": "U_Bin", "offset": 0, "scale": 500}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 100}, + {"channel": "V_Bin", "offset": 0, "scale": 500}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100}, + {"channel": "W_Bin", "offset": 0, "scale": 500}, + ], + }, + }, + }, + { + "network": "NT", + "station": "SJG", + "start_time": None, + "end_time": UTCDateTime("2023-08-18T19:02:34.000Z"), + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 100}, + {"channel": "U_Bin", "offset": 0, "scale": 500}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 100}, + {"channel": "V_Bin", "offset": 0, "scale": 500}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100}, + {"channel": "W_Bin", "offset": 0, "scale": 500}, + ], + }, + }, + }, + { + "network": "NT", + "station": "SJG", + "start_time": UTCDateTime("2023-08-18T19:02:34.000Z"), + "end_time": UTCDateTime("2023-08-30T00:00:00.000Z"), + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 27047, "scale": 313.2034}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 312.2797}], + "W": [{"channel": "W_Volt", "offset": 24288, "scale": 311.9576}], + }, + "electronics": { + "serial": "E0543", + # these scale values are calculated manually + "x-scale": 313.2034, # nT/V + "y-scale": 312.2797, # nT/V + "z-scale": 311.9576, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0419", + # these constants combine with instrument setting for offset + "x-constant": 36958, # nT/mA + "y-constant": 36849, # nT/mA + "z-constant": 36811, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "SJG", + "start_time": UTCDateTime("2023-08-30T00:00:00.000Z"), + "end_time": None, + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 26947.5, "scale": 313.2034}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 312.2797}], + "W": [{"channel": "W_Volt", "offset": 24690, "scale": 311.9576}], + }, + "electronics": { + "serial": "E0543", + # these scale values are calculated manually + "x-scale": 313.2034, # nT/V + "y-scale": 312.2797, # nT/V + "z-scale": 311.9576, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0419", + # these constants combine with instrument setting for offset + "x-constant": 36958, # nT/mA + "y-constant": 36849, # nT/mA + "z-constant": 36811, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "SJT", + "start_time": None, + "end_time": UTCDateTime("2023-08-18T19:02:34.000Z"), + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 27047, "scale": 313.2034}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 312.2797}], + "W": [{"channel": "W_Volt", "offset": 24288, "scale": 311.9576}], + }, + # this info should get updated when available + "electronics": { + "serial": "E0543", + # these scale values are calculated manually + "x-scale": 313.2034, # nT/V + "y-scale": 312.2797, # nT/V + "z-scale": 311.9576, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0419", + # these constants combine with instrument setting for offset + "x-constant": 36958, # nT/mA + "y-constant": 36849, # nT/mA + "z-constant": 36811, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "SJT", + "start_time": UTCDateTime("2023-08-18T19:02:34.000Z"), + "end_time": None, + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 100}, + {"channel": "U_Bin", "offset": 0, "scale": 500}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 100}, + {"channel": "V_Bin", "offset": 0, "scale": 500}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100}, + {"channel": "W_Bin", "offset": 0, "scale": 500}, + ], + }, + }, + }, + { + "network": "NT", + "station": "TUC", + "start_time": None, + "end_time": UTCDateTime("2023-03-29T00:00:00.000Z"), + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 100}, + {"channel": "U_Bin", "offset": 0, "scale": 500}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 100}, + {"channel": "V_Bin", "offset": 0, "scale": 500}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100}, + {"channel": "W_Bin", "offset": 0, "scale": 500}, + ], + }, + }, + }, + { + "network": "NT", + "station": "TUC", + "start_time": UTCDateTime("2023-03-29T00:00:00.000Z"), + "end_time": UTCDateTime("2023-08-30T00:00:00.000Z"), + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 24024, "scale": 978.355}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 965.901}], + "W": [{"channel": "W_Volt", "offset": 40040, "scale": 954.543}], + }, + # this info should get updated when available + "electronics": { + "serial": "E571", + # these scale values are calculated manually + "x-scale": 978.355, # nT/V + "y-scale": 965.901, # nT/V + "z-scale": 954.543, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0446", + # these constants combine with instrument setting for offset + "x-constant": 37471, # nT/mA + "y-constant": 36994, # nT/mA + "z-constant": 36559, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "TUC", + "start_time": UTCDateTime("2023-08-30T00:00:00.000Z"), + "end_time": None, + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 24016.5, "scale": 978.355}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 965.901}], + "W": [{"channel": "W_Volt", "offset": 39953.5, "scale": 954.543}], + }, + # this info should get updated when available + "electronics": { + "serial": "E571", + # these scale values are calculated manually + "x-scale": 978.355, # nT/V + "y-scale": 965.901, # nT/V + "z-scale": 954.543, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0446", + # these constants combine with instrument setting for offset + "x-constant": 37471, # nT/mA + "y-constant": 36994, # nT/mA + "z-constant": 36559, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "BRW", + "start_time": None, + "end_time": UTCDateTime("2023-10-23T20:00:00.000Z"), + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 100}, + {"channel": "U_Bin", "offset": 0, "scale": 506}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 100}, + {"channel": "V_Bin", "offset": 0, "scale": 505.6}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100}, + {"channel": "W_Bin", "offset": 0, "scale": 506}, + ], + }, + }, + }, + { + "network": "NT", + "station": "BRW", + "start_time": UTCDateTime("2023-10-23T19:00:00.000Z"), + "end_time": UTCDateTime("2023-10-24T22:45:00.000Z"), + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 9217, "scale": 5797.3}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 5777.6}], + "W": [{"channel": "W_Volt", "offset": 56442, "scale": 5895.6}], + }, + "electronics": { + "serial": "????", + # these scale values are calculated manually. + "x-scale": 5797.3, # nT/V + "y-scale": 5777.6, # nT/V + "z-scale": 5895.6, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "????", + # these constants combine with instrument setting for offset + "x-constant": None, # nT/mA + "y-constant": None, # nT/mA + "z-constant": None, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "CMO", + "start_time": None, + "end_time": UTCDateTime("2023-10-26T21:00:00.000Z"), + "instrument": { + "type": "Narod", + "channels": { + "U": [ + {"channel": "U_Volt", "offset": 0, "scale": 99.4}, + {"channel": "U_Bin", "offset": 0, "scale": 502.5}, + ], + "V": [ + {"channel": "V_Volt", "offset": 0, "scale": 101.5}, + {"channel": "V_Bin", "offset": 0, "scale": 512.5}, + ], + "W": [ + {"channel": "W_Volt", "offset": 0, "scale": 100.98}, + {"channel": "W_Bin", "offset": 0, "scale": 509.15}, + ], + }, + }, + }, + { + "network": "NT", + "station": "CMT", + "start_time": None, + "end_time": UTCDateTime("2023-10-26T21:00:00.000Z"), + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 0, "scale": 967.7}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 969.7}], + "W": [{"channel": "W_Volt", "offset": 0, "scale": 973.4}], + }, + "electronics": { + "serial": "E0568", + # these scale values are used to convert voltage + "x-scale": 967.7, # nT/V + "y-scale": 969.7, # nT/V + "z-scale": 973.4, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0443", + # these constants combine with instrument setting for offset + "x-constant": 37062, # nT/mA + "y-constant": 37141, # nT/mA + "z-constant": 37281, # nT/mA + }, + }, + }, + { + "network": "NT", + "station": "CMO", + "start_time": UTCDateTime("2023-10-26T21:00:00.000Z"), + "end_time": UTCDateTime("2023-10-27T16:20:00.000Z"), + "instrument": { + "type": "FGE", + "channels": { + # each channel maps to a list of components to calculate nT + # TODO: calculate these lists based on "FGE" type + "U": [{"channel": "U_Volt", "offset": 0, "scale": 967.7}], + "V": [{"channel": "V_Volt", "offset": 0, "scale": 969.7}], + "W": [{"channel": "W_Volt", "offset": 0, "scale": 973.4}], + }, + "electronics": { + "serial": "E0568", + # these scale values are used to convert voltage + "x-scale": 967.7, # nT/V + "y-scale": 969.7, # nT/V + "z-scale": 973.4, # nT/V + "temperature-scale": 0.01, # V/K + }, + "sensor": { + "serial": "S0443", + # these constants combine with instrument setting for offset + "x-constant": 37062, # nT/mA + "y-constant": 37141, # nT/mA + "z-constant": 37281, # nT/mA + }, + }, + }, +] diff --git a/geomagio/edge/MiniSeedFactory.py b/geomagio/edge/MiniSeedFactory.py index 63bbffe860fb2034a13fc216320a0f6bd22d61d0..1c898c637bb4ecd32078f90460e09ad5272e7c73 100644 --- a/geomagio/edge/MiniSeedFactory.py +++ b/geomagio/edge/MiniSeedFactory.py @@ -8,7 +8,6 @@ to take advantage of it's newer realtime abilities. Edge is the USGS earthquake hazard centers replacement for earthworm. """ - from __future__ import absolute_import import sys from typing import List, Optional @@ -20,7 +19,7 @@ from obspy.core import Stats, Stream, Trace, UTCDateTime from .. import ChannelConverter, TimeseriesUtility from ..geomag_types import DataInterval, DataType -from ..metadata.instrument.InstrumentCalibrations import get_instrument_calibrations +from ..Metadata import get_instrument from ..TimeseriesFactory import TimeseriesFactory from ..TimeseriesFactoryException import TimeseriesFactoryException from ..ObservatoryMetadata import ObservatoryMetadata @@ -448,7 +447,7 @@ class MiniSeedFactory(TimeseriesFactory): to contain just a single Trace. """ out = Stream() - metadata = get_instrument_calibrations(observatory, starttime, endtime) + metadata = get_instrument(observatory, starttime, endtime) # loop in case request spans different configurations for entry in metadata: entry_endtime = entry["end_time"] diff --git a/geomagio/metadata/instrument/InstrumentCalibrations.py b/geomagio/metadata/instrument/InstrumentCalibrations.py deleted file mode 100644 index e214f57249bba4de9c55960ee9fc4cb00c52ef13..0000000000000000000000000000000000000000 --- a/geomagio/metadata/instrument/InstrumentCalibrations.py +++ /dev/null @@ -1,360 +0,0 @@ -from obspy import UTCDateTime - -from geomagio.metadata import Metadata, MetadataFactory, MetadataCategory - -# REMOVE ANY INSTRUMENT METADATA ELEMENTS W/ "DATA_VALID=FALSE" - - -class InstrumentCalibrations: - """ - A class used to get calibrations from instrument metadata. - - ... - - Attributes - ---------- - metadata_list : list - a list of metadata objects to be processed - previous_calibration : dict - a dictionary to store the previous calibration values for each axis and key - station : str - the station code, checked for consistency across all metadata objects - location : str - the location code, checked for consistency across all metadata objects - network : str - the network code, checked for consistency across all metadata objects - - Methods - ------- - get_calibrations(): - Main method to gather applicable calibrations from the metadata list. - create_overlap_interval(current_metadata): - Creates an overlap interval from the current metadata. - update_overlap_interval(overlap_interval, current_metadata): - Updates the overlap interval with the current metadata. - update_overlap_interval_with_same_starttime(i, sorted_metadata_list, overlap_interval): - Updates the overlap interval with metadata that have the same starttime. - set_endtime(i, sorted_metadata_list, overlap_interval, current_metadata): - Sets the endtime for the overlap interval. - convert_to_calibration(overlap_metadata): - Converts overlapping metadata information to an applicable calibration. - get_channels(overlap_metadata): - Gets the channels for the applicable calibration. - """ - - def __init__(self, metadata_list): - """ - Constructs necessary attributes for the InstrumentCalibrations object and verify consistency of metadata_list. - - Parameters - ---------- - metadata_list : list - a list of metadata objects to be processed - """ - self.metadata_list = metadata_list - self.previous_calibration = { - f"{axis}_{key}": None - for axis in ["u", "v", "w"] - for key in ["constant", "bin", "offset"] - } - self.previous_calibration.update( - {"resistance": None, "temperature_scale": None, "type": None} - ) - - # Check for consistency in "station", "location", and "network" codes - stations = {metadata.station for metadata in metadata_list} - locations = {metadata.location for metadata in metadata_list} - networks = {metadata.network for metadata in metadata_list} - - if len(stations) > 1: # or len(locations) > 1: - raise ValueError( - f"Inconsistent 'station' codes in metadata_list: {stations}" - ) - else: - self.station = stations.pop() - self.location = locations.pop() - self.network = networks.pop() - - def get_calibrations(self): - """ - Main method to compile applicable calibrations from the metadata list. - - Parameters - ---------- - query_starttime : UTCDateTime - the query starttime - - Returns - ------- - list - a list of dictionaries, each representing an applicable calibration - """ - sorted_metadata_list = sorted( - self.metadata_list, - key=lambda x: x.starttime if x.starttime is not None else UTCDateTime(0), - ) - i = 0 - calibrations = [] - while i < len(sorted_metadata_list): - current_metadata = sorted_metadata_list[i] - overlap_interval = self.create_overlap_interval(current_metadata) - i = self.update_overlap_interval_with_same_starttime( - i, sorted_metadata_list, overlap_interval - ) - self.set_endtime( - i, sorted_metadata_list, overlap_interval, current_metadata - ) - calibration = self.convert_to_calibration(overlap_interval) - # if ( - # calibration["end_time"] >= query_starttime - # or calibration["end_time"] == None - # ): - calibrations.append(calibration) - i += 1 - return calibrations - - def create_overlap_interval(self, current_metadata): - """ - Creates an overlap interval from the current metadata. - - Parameters - ---------- - current_metadata : Metadata - the current metadata object - - Returns - ------- - dict - a dictionary representing an overlap interval - """ - overlap_interval = {"starttime": current_metadata.starttime} - self.update_overlap_interval(overlap_interval, current_metadata) - return overlap_interval - - def update_overlap_interval(self, overlap_interval, current_metadata): - """ - Updates the overlap interval with the current metadata. - - Parameters - ---------- - overlap_interval : dict - the overlap interval to be updated - current_metadata : Metadata - the current metadata object - """ - for axis in ["u", "v", "w"]: - for key in ["constant", "bin", "offset"]: - current_key = f"{axis}_{key}" - if current_key in current_metadata.metadata: - overlap_interval[current_key] = current_metadata.metadata[ - current_key - ] - self.previous_calibration[current_key] = current_metadata.metadata[ - current_key - ] - elif current_key in self.previous_calibration: - overlap_interval[current_key] = self.previous_calibration[ - current_key - ] - for key in ["resistance", "temperature_scale", "type"]: - if key in current_metadata.metadata: - overlap_interval[key] = current_metadata.metadata[key] - self.previous_calibration[key] = current_metadata.metadata[key] - elif key in self.previous_calibration: - overlap_interval[key] = self.previous_calibration[key] - - def update_overlap_interval_with_same_starttime( - self, i, sorted_metadata_list, overlap_interval - ): - """ - Updates the overlap interval with metadata that have the same starttime. - - Parameters - ---------- - i : int - the current index in the sorted metadata list - sorted_metadata_list : list - the sorted list of metadata objects - overlap_interval : dict - the overlap interval to be updated - - Returns - ------- - int - the updated index in the sorted metadata list - """ - while ( - i + 1 < len(sorted_metadata_list) - and sorted_metadata_list[i + 1].starttime - == sorted_metadata_list[i].starttime - ): - i += 1 - next_metadata = sorted_metadata_list[i] - self.update_overlap_interval(overlap_interval, next_metadata) - return i - - def set_endtime(self, i, sorted_metadata_list, overlap_interval, current_metadata): - """ - Sets the endtime for the overlap interval. - - Parameters - ---------- - i : int - the current index in the sorted metadata list - sorted_metadata_list : list - the sorted list of metadata objects - overlap_interval : dict - the overlap interval to be updated - current_metadata : Metadata - the current metadata object - """ - if ( - i + 1 < len(sorted_metadata_list) - and sorted_metadata_list[i + 1].starttime != current_metadata.starttime - ): - overlap_interval["endtime"] = sorted_metadata_list[i + 1].starttime - else: - overlap_interval["endtime"] = current_metadata.endtime - - def convert_to_calibration(self, overlap_metadata): - """ - Converts an overlap_metadata object to an applicable calibration. - - Parameters - ---------- - overlap_metadata : dict - the metadata overlap data to be converted - - Returns - ------- - dict - a dictionary representing an applicable calibration - """ - calibration = { - "network": self.network, - "station": self.station, - "location": self.location, - "start_time": overlap_metadata["starttime"], - "end_time": overlap_metadata["endtime"], - "instrument": { - "type": overlap_metadata["type"], - "channels": self.get_channels(overlap_metadata), - }, - } - return calibration - - def get_channels(self, overlap_metadata): - """ - Gets the channels for the applicable calibration. - - Parameters - ---------- - overlap_metadata : dict - the metadata overlap data from which to get the channels - - Returns - ------- - dict - a dictionary representing the channels for the applicable calibration - """ - channels = {} - for axis in ["U", "V", "W"]: - if ( - f"{axis.lower()}_bin" in overlap_metadata - and overlap_metadata[f"{axis.lower()}_bin"] is not None - ): - channels[axis] = [ - { - "channel": f"{axis}_Volt", - "offset": ( - overlap_metadata[f"{axis.lower()}_offset"] - if overlap_metadata[f"{axis.lower()}_offset"] is not None - else 0 - ), - "scale": overlap_metadata[f"{axis.lower()}_constant"], - }, - { - "channel": f"{axis}_Bin", - "offset": 0, - "scale": overlap_metadata[f"{axis.lower()}_bin"], - }, - ] - elif ( - "resistance" in overlap_metadata - and overlap_metadata["resistance"] is not None - ): - channels[axis] = [ - { - "channel": f"{axis}_Volt", - "offset": ( - overlap_metadata[f"{axis.lower()}_offset"] - if overlap_metadata[f"{axis.lower()}_offset"] is not None - else 0 - ), - "scale": overlap_metadata[f"{axis.lower()}_constant"] - / overlap_metadata["resistance"], - } - ] - return channels - - -def get_instrument_calibrations( - observatory, start_time=None, end_time=None, calibrations=None, metadata_url=None -): - """Get instrument metadata - - Args: - observatory: observatory code - start_time: start time to match, or None to match any. - end_time: end time to match, or None to match any. - calibrations: use custom list, defaults to pulling and converting instrument metadata - metadata_url: metadata database url - Returns: - list of applicable instrument calibrations - """ - - if not calibrations: - factory = MetadataFactory( - url=metadata_url or "https://staging-geomag.cr.usgs.gov/ws/secure/metadata", - ) - query = Metadata( - category=MetadataCategory.INSTRUMENT, - starttime=start_time, - endtime=end_time, - station=observatory, - ) - metadata = factory.get_metadata(query=query) - - # remove invalid metadata entries - for i, m in enumerate(metadata): - if not m.data_valid or "instrument_category" not in m.metadata: - metadata.remove(m) - - if not metadata or metadata is None: - raise ValueError( - f"No valid metadata returned for {observatory} for time interval: {start_time} - {end_time}" - ) - else: - instrumentCalibrations = InstrumentCalibrations(metadata) - calibrations = instrumentCalibrations.get_calibrations() - - if not calibrations or calibrations is None: - raise ValueError( - f"No valid calibrations returned for {observatory} for time interval: {start_time} - {end_time}" - ) - else: - return [ - c - for c in calibrations - if c["station"] == observatory - and ( - end_time is None - or c["start_time"] is None - or c["start_time"] < end_time - ) - and ( - start_time is None - or c["end_time"] is None - or c["end_time"] > start_time - ) - ] diff --git a/geomagio/metadata/instrument/__init__.py b/geomagio/metadata/instrument/__init__.py deleted file mode 100644 index c470473d1dcbd0aab8e8985c965267b10585d82f..0000000000000000000000000000000000000000 --- a/geomagio/metadata/instrument/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from .InstrumentCalibrations import InstrumentCalibrations - - -__all__ = [ - "InstrumentCalibrations", -] diff --git a/test/Metadata_test.py b/test/Metadata_test.py index 141a657c16e8046f9e4df22274891c538d45df26..01e5e417144c6b3ac4c1a9557dcea7b07934a8ae 100644 --- a/test/Metadata_test.py +++ b/test/Metadata_test.py @@ -1,7 +1,5 @@ from obspy import UTCDateTime -from geomagio.metadata.instrument.InstrumentCalibrations import ( - get_instrument_calibrations, -) +from geomagio.Metadata import get_instrument from numpy.testing import assert_equal @@ -28,7 +26,7 @@ TEST_METADATA = [METADATA1, METADATA2, METADATA3] def test_get_instrument_after(): """Request an interval after the last entry, that has start_time None""" - matches = get_instrument_calibrations( + matches = get_instrument( "TST", UTCDateTime("2021-02-02T00:00:00Z"), UTCDateTime("2022-01-02T00:00:00Z"), @@ -39,7 +37,7 @@ def test_get_instrument_after(): def test_get_instrument_before(): """Request an interval before the first entry, that has start_time None""" - matches = get_instrument_calibrations( + matches = get_instrument( "TST", UTCDateTime("2019-02-02T00:00:00Z"), UTCDateTime("2020-01-02T00:00:00Z"), @@ -50,7 +48,7 @@ def test_get_instrument_before(): def test_get_instrument_inside(): """Request an interval that is wholly contained by one entry""" - matches = get_instrument_calibrations( + matches = get_instrument( "TST", UTCDateTime("2020-02-02T01:00:00Z"), UTCDateTime("2020-02-02T02:00:00Z"), @@ -61,7 +59,7 @@ def test_get_instrument_inside(): def test_get_instrument_span(): """Request a time interval that spans multiple entries""" - matches = get_instrument_calibrations( + matches = get_instrument( "TST", UTCDateTime("2020-01-02T00:00:00Z"), UTCDateTime("2020-02-02T01:00:00Z"), @@ -72,7 +70,7 @@ def test_get_instrument_span(): def test_get_instrument_unknown(): """Request an unknown observatory""" - matches = get_instrument_calibrations( + matches = get_instrument( "OTHER", UTCDateTime("2020-01-02T00:00:00Z"), UTCDateTime("2020-02-02T01:00:00Z"), diff --git a/test/edge_test/MiniSeedFactory_test.py b/test/edge_test/MiniSeedFactory_test.py index 75f895e5c8a7a2bb83d0bdbe9215076a52095635..6b0dbbd91436911d003646887bcd581cc4925df0 100644 --- a/test/edge_test/MiniSeedFactory_test.py +++ b/test/edge_test/MiniSeedFactory_test.py @@ -1,5 +1,4 @@ """Tests for MiniSeedFactory.py""" - import io from typing import List @@ -10,9 +9,7 @@ import pytest from geomagio import TimeseriesUtility from geomagio.edge import MiniSeedFactory, MiniSeedInputClient -from geomagio.metadata.instrument.InstrumentCalibrations import ( - get_instrument_calibrations, -) +from geomagio.Metadata import get_instrument from .mseed_test_clients import MockMiniSeedClient, MisalignedMiniSeedClient @@ -46,7 +43,7 @@ def misaligned_miniseed_factory() -> MiniSeedFactory: @pytest.fixture() def bou_u_metadata(): - metadata = get_instrument_calibrations(observatory="BOU") + metadata = get_instrument(observatory="BOU") instrument = metadata[0]["instrument"] channels = instrument["channels"] yield channels["U"]