TFA: Time-Frequency Analysis#

An overview of usage of the TFA toolbox. (To be separated out into different notebooks as before, overwriting those old ones)

%load_ext autoreload
%autoreload 2
import datetime as dt
import matplotlib.pyplot as plt
import numpy as np

from swarmpal.io import create_paldata, PalDataItem
from swarmpal.toolboxes import tfa

MAGx_LR example#

Fetching data#

data_params = dict(
    collection="SW_OPER_MAGA_LR_1B",
    measurements=["B_NEC", "F"],
    models=["Model='CHAOS-Core'+'CHAOS-Static'"],
    auxiliaries=["QDLat", "MLT"],
    start_time=dt.datetime(2015, 3, 14),
    end_time=dt.datetime(2015, 3, 14, 3, 59, 59),
    pad_times=(dt.timedelta(hours=3), dt.timedelta(hours=3)),
    server_url="https://vires.services/ows",
    options=dict(asynchronous=False, show_progress=False),
)
data = create_paldata(PalDataItem.from_vires(**data_params))
print(data)
DataTree('paldata', parent=None)
└── DataTree('SW_OPER_MAGA_LR_1B')
        Dimensions:      (Timestamp: 35999, NEC: 3)
        Coordinates:
          * Timestamp    (Timestamp) datetime64[ns] 2015-03-13T21:00:00 ... 2015-03-1...
          * NEC          (NEC) <U1 'N' 'E' 'C'
        Data variables:
            Spacecraft   (Timestamp) object 'A' 'A' 'A' 'A' 'A' ... 'A' 'A' 'A' 'A' 'A'
            Radius       (Timestamp) float64 6.835e+06 6.835e+06 ... 6.83e+06 6.83e+06
            Latitude     (Timestamp) float64 1.825 1.889 1.953 ... 34.16 34.1 34.03
            B_NEC_Model  (Timestamp, NEC) float64 2.177e+04 -4.168e+03 ... 2.571e+04
            QDLat        (Timestamp) float64 -9.028 -8.964 -8.9 ... 27.26 27.18 27.11
            F            (Timestamp) float64 2.354e+04 2.355e+04 ... 3.466e+04 3.464e+04
            MLT          (Timestamp) float64 19.82 19.82 19.82 ... 7.813 7.813 7.813
            B_NEC        (Timestamp, NEC) float64 2.175e+04 -4.166e+03 ... 2.572e+04
            Longitude    (Timestamp) float64 -15.47 -15.47 -15.47 ... 12.1 12.1 12.1
            F_Model      (Timestamp) float64 2.357e+04 2.357e+04 ... 3.466e+04 3.464e+04
        Attributes:
            Sources:         ['CHAOS-7_static.shc', 'SW_OPER_MAGA_LR_1B_20150313T0000...
            MagneticModels:  ["Model = 'CHAOS-Core'(max_degree=20,min_degree=1) + 'CH...
            AppliedFilters:  []
            PAL_meta:        {"analysis_window": ["2015-03-14T00:00:00", "2015-03-14T...

Applying processes#

TFA: Preprocess#

p1 = tfa.processes.Preprocess()
p1.set_config(
    dataset="SW_OPER_MAGA_LR_1B",
    active_variable="B_MFA",
    active_component=2,
    sampling_rate=1,
    remove_model=True,
    convert_to_mfa=True,
)
p1(data)
print(data)
DataTree('paldata', parent=None)
│   Dimensions:  ()
│   Data variables:
│       *empty*
│   Attributes:
│       PAL_meta:  {"TFA_Preprocess": {"dataset": "SW_OPER_MAGA_LR_1B", "timevar"...
└── DataTree('SW_OPER_MAGA_LR_1B')
        Dimensions:          (Timestamp: 35999, NEC: 3, MFA: 3, TFA_Time: 35999)
        Coordinates:
          * Timestamp        (Timestamp) datetime64[ns] 2015-03-13T21:00:00 ... 2015-...
          * NEC              (NEC) <U1 'N' 'E' 'C'
          * MFA              (MFA) int64 0 1 2
          * TFA_Time         (TFA_Time) datetime64[ns] 2015-03-13T21:00:00 ... 2015-0...
        Data variables: (12/13)
            Spacecraft       (Timestamp) object 'A' 'A' 'A' 'A' 'A' ... 'A' 'A' 'A' 'A'
            Radius           (Timestamp) float64 6.835e+06 6.835e+06 ... 6.83e+06
            Latitude         (Timestamp) float64 1.825 1.889 1.953 ... 34.16 34.1 34.03
            B_NEC_Model      (Timestamp, NEC) float64 2.177e+04 -4.168e+03 ... 2.571e+04
            QDLat            (Timestamp) float64 -9.028 -8.964 -8.9 ... 27.18 27.11
            F                (Timestamp) float64 2.354e+04 2.355e+04 ... 3.464e+04
            ...               ...
            B_NEC            (Timestamp, NEC) float64 2.175e+04 -4.166e+03 ... 2.572e+04
            Longitude        (Timestamp) float64 -15.47 -15.47 -15.47 ... 12.1 12.1 12.1
            F_Model          (Timestamp) float64 2.357e+04 2.357e+04 ... 3.464e+04
            B_NEC_res_Model  (Timestamp, NEC) float64 -24.7 2.017 4.414 ... -4.758 10.28
            B_MFA            (Timestamp, MFA) float64 4.208 -2.663 ... -4.483 0.6429
            TFA_Variable     (TFA_Time) float64 -24.67 -24.66 -24.68 ... 0.6687 0.6429
        Attributes:
            Sources:         ['CHAOS-7_static.shc', 'SW_OPER_MAGA_LR_1B_20150313T0000...
            MagneticModels:  ["Model = 'CHAOS-Core'(max_degree=20,min_degree=1) + 'CH...
            AppliedFilters:  []
            PAL_meta:        {"analysis_window": ["2015-03-14T00:00:00", "2015-03-14T...

This data has been extended to include B_NEC_res_Model, B_MFA, and TFA_Variable. These can be inspected with the usual xarray/matplotlib tools

fig, axes = plt.subplots(3, 1, sharex=True)
data["SW_OPER_MAGA_LR_1B"]["B_NEC"].plot.line(x="Timestamp", ax=axes[0])
data["SW_OPER_MAGA_LR_1B"]["B_NEC_res_Model"].plot.line(x="Timestamp", ax=axes[1])
data["SW_OPER_MAGA_LR_1B"]["B_MFA"].plot.line(x="Timestamp", ax=axes[2])
axes[1].set_ylim(-200, 200)
axes[2].set_ylim(-200, 200);
../../_images/56efe59455cc98e100a0729c1057d1938b38d52e0a6b4d1a9c879c405bc078f3.png
data["SW_OPER_MAGA_LR_1B"]["TFA_Variable"].plot.line(x="TFA_Time");
../../_images/931c88d425476362f142a4efc4d7756945522077f6aaaaee1b3a07ab8a71cc62.png

TFA: Clean#

p2 = tfa.processes.Clean()
p2.set_config(
    window_size=300,
    method="iqr",
    multiplier=1,
)
p2(data)
data["SW_OPER_MAGA_LR_1B"]["TFA_Variable"].plot.line(x="TFA_Time");
../../_images/be66b8f3f9388bc7aa1311b63ece39d2b5f9c7e8543ad53dcb3cf289f59c6b42.png

TFA: Filter#

p3 = tfa.processes.Filter()
p3.set_config(
    cutoff_frequency=20 / 1000,
)
p3(data)
data["SW_OPER_MAGA_LR_1B"]["TFA_Variable"].plot.line(x="TFA_Time");
../../_images/382eb2d0928436988ac284ab2dc99a76026549500cb946a60ebd025836d8499b.png

TFA: Wavelet#

p4 = tfa.processes.Wavelet()
p4.set_config(
    min_frequency=20 / 1000,
    max_frequency=100 / 1000,
    dj=0.1,
)
p4(data)
print(data)
DataTree('paldata', parent=None)
│   Dimensions:  ()
│   Data variables:
│       *empty*
│   Attributes:
│       PAL_meta:  {"TFA_Preprocess": {"dataset": "SW_OPER_MAGA_LR_1B", "timevar"...
└── DataTree('SW_OPER_MAGA_LR_1B')
        Dimensions:          (Timestamp: 35999, NEC: 3, MFA: 3, TFA_Time: 35999,
                              scale: 24)
        Coordinates:
          * Timestamp        (Timestamp) datetime64[ns] 2015-03-13T21:00:00 ... 2015-...
          * NEC              (NEC) <U1 'N' 'E' 'C'
          * MFA              (MFA) int64 0 1 2
          * TFA_Time         (TFA_Time) datetime64[ns] 2015-03-13T21:00:00 ... 2015-0...
          * scale            (scale) float64 10.0 10.72 11.49 ... 42.87 45.95 49.25
        Data variables: (12/14)
            Spacecraft       (Timestamp) object 'A' 'A' 'A' 'A' 'A' ... 'A' 'A' 'A' 'A'
            Radius           (Timestamp) float64 6.835e+06 6.835e+06 ... 6.83e+06
            Latitude         (Timestamp) float64 1.825 1.889 1.953 ... 34.16 34.1 34.03
            B_NEC_Model      (Timestamp, NEC) float64 2.177e+04 -4.168e+03 ... 2.571e+04
            QDLat            (Timestamp) float64 -9.028 -8.964 -8.9 ... 27.18 27.11
            F                (Timestamp) float64 2.354e+04 2.355e+04 ... 3.464e+04
            ...               ...
            Longitude        (Timestamp) float64 -15.47 -15.47 -15.47 ... 12.1 12.1 12.1
            F_Model          (Timestamp) float64 2.357e+04 2.357e+04 ... 3.464e+04
            B_NEC_res_Model  (Timestamp, NEC) float64 -24.7 2.017 4.414 ... -4.758 10.28
            B_MFA            (Timestamp, MFA) float64 4.208 -2.663 ... -4.483 0.6429
            TFA_Variable     (TFA_Time) float64 -0.02522 -0.02383 ... 0.03256 0.07105
            wavelet_power    (scale, TFA_Time) float64 2.69e-05 2.458e-05 ... 9.341e-06
        Attributes:
            Sources:         ['CHAOS-7_static.shc', 'SW_OPER_MAGA_LR_1B_20150313T0000...
            MagneticModels:  ["Model = 'CHAOS-Core'(max_degree=20,min_degree=1) + 'CH...
            AppliedFilters:  []
            PAL_meta:        {"analysis_window": ["2015-03-14T00:00:00", "2015-03-14T...

Plotting#

Special plotting functions are available under swarmpal.toolboxes.tfa.plotting. These accept the above datatree (data) as input.

Note that by default (see clip_times=True), these plots are restricted to the analysis window (the full time window minus the time pads added in the data request).

tfa.plotting.time_series(data)
(<Figure size 640x480 with 1 Axes>,
 <AxesSubplot: xlabel='Time', ylabel='TFA: B_MFA (nT)'>)
../../_images/e38c603bc024b461b3d1dedf0a457cc8ab87bffede1d1a62d014a73db9278180.png
tfa.plotting.spectrum(data, levels=np.linspace(-6, -1, 20))
(<Figure size 640x480 with 2 Axes>,
 <AxesSubplot: xlabel='Time', ylabel='Frequency [mHz]'>)
../../_images/80fe9d8e2d18c37633d879bb93830db7f840f0168180dfc964a7628981840b17.png
tfa.plotting.quicklook(data)
(<Figure size 1500x600 with 4 Axes>,
 (<AxesSubplot: ylabel='TFA: B_MFA (nT)'>,
  <AxesSubplot: xlabel='Time', ylabel='wave_index'>,
  <AxesSubplot: xlabel='Time', ylabel='Frequency [mHz]'>))
../../_images/6e5ce48e9b9525c73796b679ac18270d701fe0a615d3f8e06e3fcb559030b18b.png

The plots can be configured with extra options like tlims (subsetting the time to plot), and extra_x (defining which extra x-axes to make).

tfa.plotting.quicklook(
    data,
    tlims=("2015-03-14T03:00:00", "2015-03-14T03:30:00"),
    extra_x=("QDLat", "MLT", "Latitude"),
)
(<Figure size 1500x600 with 4 Axes>,
 (<AxesSubplot: ylabel='TFA: B_MFA (nT)'>,
  <AxesSubplot: xlabel='Time', ylabel='wave_index'>,
  <AxesSubplot: xlabel='Time', ylabel='Frequency [mHz]'>))
../../_images/65a79037cef648e32da0cafa7ddeea16323a3506ebb7e5c54966c2b55152e276.png

MAGx_HR#

data_params = dict(
    collection="SW_OPER_MAGB_HR_1B",
    measurements=["B_NEC"],
    models=["Model='CHAOS-Core'+'CHAOS-Static'"],
    auxiliaries=["QDLat", "MLT"],
    start_time=dt.datetime(2015, 3, 14, 12, 5, 0),
    end_time=dt.datetime(2015, 3, 14, 12, 30, 0),
    pad_times=(dt.timedelta(minutes=10), dt.timedelta(minutes=10)),
    server_url="https://vires.services/ows",
    options=dict(asynchronous=False, show_progress=False),
)
data = create_paldata(PalDataItem.from_vires(**data_params))
p1 = tfa.processes.Preprocess()
p1.set_config(
    dataset="SW_OPER_MAGB_HR_1B",
    active_variable="B_NEC_res_Model",
    sampling_rate=50,
    remove_model=True,
    use_magnitude=True,
)
p2 = tfa.processes.Clean()
p2.set_config(
    window_size=300,
    method="iqr",
    multiplier=1,
)
p3 = tfa.processes.Filter()
p3.set_config(
    cutoff_frequency=0.1,
)
p4 = tfa.processes.Wavelet()
p4.set_config(
    min_frequency=1,
    max_frequency=25,
    dj=0.1,
)
p1(data)
p2(data)
p3(data)
p4(data);
fig, ax = plt.subplots(1, 1, figsize=(15, 5))
tfa.plotting.spectrum(data, levels=np.linspace(-6, -3, 20), ax=ax)
(None, <AxesSubplot: xlabel='Time', ylabel='Frequency [mHz]'>)
../../_images/b3ac1dd5fa59d0f21769b35ee1d2fefa705e6e1bac8267b42b186db587cb0b9e.png

EFIx_TCT#

data_params = dict(
    collection="SW_EXPT_EFIA_TCT02",
    measurements=["Ehx", "Ehy", "Ehz", "Quality_flags"],
    auxiliaries=["QDLat", "MLT"],
    start_time=dt.datetime(2015, 3, 14, 12, 5, 0),
    end_time=dt.datetime(2015, 3, 14, 12, 30, 0),
    pad_times=(dt.timedelta(hours=3), dt.timedelta(hours=3)),
    server_url="https://vires.services/ows",
    options=dict(asynchronous=False, show_progress=False),
)
data = create_paldata(PalDataItem.from_vires(**data_params))
p1 = tfa.processes.Preprocess()
p1.set_config(
    dataset="SW_EXPT_EFIA_TCT02",
    active_variable="Eh_XYZ",
    active_component=2,
    sampling_rate=2,
)
p2 = tfa.processes.Clean()
p2.set_config(
    window_size=300,
    method="iqr",
    multiplier=1,
)
p3 = tfa.processes.Filter()
p3.set_config(
    cutoff_frequency=20 / 1000,
)
p4 = tfa.processes.Wavelet()
p4.set_config(
    min_frequency=20 / 1000,
    max_frequency=200 / 1000,
    dj=0.1,
)
p1(data)
p2(data)
p3(data)
p4(data);
tfa.plotting.time_series(data)
(<Figure size 640x480 with 1 Axes>,
 <AxesSubplot: xlabel='Time', ylabel='TFA: Eh_XYZ'>)
../../_images/35b38fc4150654cd37cc710b4649c00f9fe49a45c4816d80cbf60a7287567591.png
tfa.plotting.spectrum(data, levels=np.linspace(-2, 2, 20))
(<Figure size 640x480 with 2 Axes>,
 <AxesSubplot: xlabel='Time', ylabel='Frequency [mHz]'>)
../../_images/75ca2527e9747700966c44cd57ddc7a4e15a5c9b651727ef3e882ac201a74284.png

AUX_OBS#

data_params = dict(
    collection="SW_OPER_AUX_OBSM2_:HRN",
    measurements=["B_NEC"],
    models=["Model='CHAOS-Core'+'CHAOS-Static'"],
    auxiliaries=["MLT"],
    start_time=dt.datetime(2015, 3, 14, 0, 0, 0),
    end_time=dt.datetime(2015, 3, 14, 23, 59, 59),
    pad_times=(dt.timedelta(hours=3), dt.timedelta(hours=3)),
    server_url="https://vires.services/ows",
    options=dict(asynchronous=False, show_progress=False),
)
data = create_paldata(PalDataItem.from_vires(**data_params))

p1 = tfa.processes.Preprocess()
p1.set_config(
    dataset="SW_OPER_AUX_OBSM2_:HRN",
    active_variable="B_NEC_res_Model",
    active_component=0,
    sampling_rate=1 / 60,
    remove_model=True,
)
p2 = tfa.processes.Clean()
p2.set_config(
    window_size=10,
    method="iqr",
    multiplier=1,
)
p3 = tfa.processes.Filter()
p3.set_config(
    cutoff_frequency=0.001,
)
p4 = tfa.processes.Wavelet()
p4.set_config(
    min_scale=1000 / 8,
    max_scale=1000 / 1,
    dj=0.1,
)

p1(data)
p2(data)
p3(data)
p4(data)

tfa.plotting.spectrum(data, levels=np.linspace(-2, 2))
Accessing INTERMAGNET and/or WDC data
Check usage terms at ftp://ftp.nerc-murchison.ac.uk/geomag/Swarm/AUX_OBS/minute/README
WARNING:swarmpal.toolboxes.tfa.plotting: Skipping QDLat: not available in data
(<Figure size 640x480 with 2 Axes>,
 <AxesSubplot: xlabel='Time', ylabel='Frequency [mHz]'>)
../../_images/dafae2838a7ab32ccfec6da6d1eee399c531498398155c0767e85b7742ab05cf.png

Cluster#

(Experimental) Note that these data are retrieved from the NASA CDAWeb HAPI server, and arguments to the data fetcher are supplied differently.

data_params = dict(
    server="https://cdaweb.gsfc.nasa.gov/hapi",
    dataset="C3_CP_FGM_SPIN",
    parameters="B_vec_xyz_gse__C3_CP_FGM_SPIN",
    start="2015-03-29T17:00:00",
    stop="2015-03-29T19:00:00",
    pad_times=(dt.timedelta(hours=3), dt.timedelta(hours=3)),
)
data = create_paldata(PalDataItem.from_hapi(**data_params))
print(data)
DataTree('paldata', parent=None)
└── DataTree('C3_CP_FGM_SPIN')
        Dimensions:                        (Time: 6839,
                                            B_vec_xyz_gse__C3_CP_FGM_SPIN_dim1: 3)
        Coordinates:
          * Time                           (Time) datetime64[ns] 2015-03-29T14:00:02....
        Dimensions without coordinates: B_vec_xyz_gse__C3_CP_FGM_SPIN_dim1
        Data variables:
            B_vec_xyz_gse__C3_CP_FGM_SPIN  (Time, B_vec_xyz_gse__C3_CP_FGM_SPIN_dim1) float64 ...
        Attributes:
            PAL_meta:  {"analysis_window": ["2015-03-29T17:00:00", "2015-03-29T19:00:...
/home/docs/checkouts/readthedocs.org/user_builds/swarmpal/envs/pre-cleanup/lib/python3.8/site-packages/hapiclient/hapitime.py:287: UserWarning: The argument 'infer_datetime_format' is deprecated and will be removed in a future version. A strict version of it is now the default, see https://pandas.pydata.org/pdeps/0004-consistent-to-datetime-parsing.html. You can safely remove this argument.
  Time = pandas.to_datetime(Time, infer_datetime_format=True).tz_convert(tzinfo).to_pydatetime()
p1 = tfa.processes.Preprocess()
p1.set_config(
    dataset="C3_CP_FGM_SPIN",
    timevar="Time",
    active_variable="B_vec_xyz_gse__C3_CP_FGM_SPIN",
    active_component=2,
    sampling_rate=1 / 4,
)
p2 = tfa.processes.Clean()
p2.set_config(
    window_size=300,
    method="iqr",
    multiplier=1,
)
p3 = tfa.processes.Filter()
p3.set_config(
    cutoff_frequency=0.1,
)
p4 = tfa.processes.Wavelet()
p4.set_config(
    min_frequency=1,
    max_frequency=25,
    dj=0.1,
)

data = data.pipe(p1).pipe(p2).pipe(p3).pipe(p4)
tfa.plotting.quicklook(data, extra_x=None);
../../_images/d2e974e56d5659d013d6ad05681fcb984b114888f0566371037eee9807b5b02b.png