MITx (Mid-lat ionospheric trough)

MITx (Mid-lat ionospheric trough)#

Abstract: Access to the MITx_LP and MITxTEC products from the PRISM project. These give information about the boundaries and minima of the midlatitude ionospheric trough derived from the Langmuir Probe (LP) measurements and Total Electron Content (TEC) respectively.

See also:

%load_ext watermark
%watermark -i -v -p viresclient,pandas,xarray,matplotlib
Python implementation: CPython
Python version       : 3.11.6
IPython version      : 8.18.0

viresclient: 0.12.0
pandas     : 2.1.3
xarray     : 2023.12.0
matplotlib : 3.8.2
import datetime as dt
import matplotlib.pyplot as plt
from viresclient import SwarmRequest

PRISM product information#

The PRISM project (Plasmapause Related boundaries in the topside Ionosphere as derived from Swarm Measurements) has two data product outputs derived from Swarm which provide the minima of the mid-latitude ionospheric trough (MIT):
MITx_LP: derived from the Langmuir Probe (LP)
MITxTEC: derived from the GPS Total Electron Content (TEC)

These are implemented in VirES as four collection types:
SW_OPER_MITx_LP_2F
SW_OPER_MITx_LP_2F:ID
SW_OPER_MITxTEC_2F
SW_OPER_MITxTEC_2F:ID
where x = A/B/C for each spacecraft.

The base collections (SW_OPER_MITx_LP_2F and SW_OPER_MITxTEC_2F) contain information on the positions of the MIT minima. The sub-collections with :ID appended contain information on the boundaries.

Similarly, the midnight plasmapause index (PPI) is provided in the collections:
SW_OPER_PPIxFAC_2F
SW_OPER_PPIxFAC_2F:ID

For details about the products and their derivation, see the documentation links on the project page.

For further details about the implementation in VirES, see:

Let’s now look at the variables available within each collection:

request = SwarmRequest()
print("MITx_LP variables:\n", request.available_measurements("SW_OPER_MITA_LP_2F"))
print("MITx_LP:ID variables:\n", request.available_measurements("SW_OPER_MITA_LP_2F:ID"))
MITx_LP variables:
 ['Counter', 'Latitude_QD', 'Longitude_QD', 'MLT_QD', 'L_value', 'SZA', 'Ne', 'Te', 'Depth', 'DR', 'Width', 'dL', 'PW_Gradient', 'EW_Gradient', 'Quality']
MITx_LP:ID variables:
 ['Counter', 'Latitude_QD', 'Longitude_QD', 'MLT_QD', 'L_value', 'SZA', 'Ne', 'Te', 'Position_Quality', 'PointType']
request = SwarmRequest()
print("MITxTEC variables:\n", request.available_measurements("SW_OPER_MITATEC_2F"))
print("MITxTEC:ID variables:\n", request.available_measurements("SW_OPER_MITATEC_2F:ID"))
MITxTEC variables:
 ['Counter', 'Latitude_QD', 'Longitude_QD', 'MLT_QD', 'L_value', 'SZA', 'TEC', 'Depth', 'DR', 'Width', 'dL', 'PW_Gradient', 'EW_Gradient', 'Quality']
MITxTEC:ID variables:
 ['Counter', 'Latitude_QD', 'Longitude_QD', 'MLT_QD', 'L_value', 'SZA', 'TEC', 'Position_Quality', 'PointType']

The difference between the LP-derived and TEC-derived datasets is the presence of either the variables Ne, Te or TEC reflecting their origin (the LP one being derived from electron density and temperature measurements from the Langmuir Probe, and the TEC one being derived from the Total Electron Content estimates).

In both cases, the dataset is split between the base collection, e.g. SW_OPER_MITA_LP_2F, and the sub-collection marked with :ID, e.g. SW_OPER_MITA_LP_2F:ID. This separation is made in order to fit the data model requirements within VirES. The base collections contain information about the minima of the MIT, and the :ID collections contain the identified boundaries (e.g. poleward/equatorward edges etc) encoded within the variables, PointType, and PositionQuality.

mitx_lp_vars = [
    # 2D variable: orbit number and quarter-orbit
    "Counter",
    # Redundant with VirES auxiliaries, QDLat, QDLon, MLT
    "Latitude_QD", "Longitude_QD", "MLT_QD",
    # Parameters characterising the identified MIT minima
    # McIlwain L-parameter, solar zenith angle, electron density and temperature
    "L_value", "SZA", "Ne", "Te",
    # Depth and relative change in density of the MIT
    "Depth", "DR",
    # Width of the MIT, in QD latitudes, and in L-values
    "Width", "dL",
    # Change in log electron density divided by QD latitude difference,
    # at the poleward and equatorward walls of the MIT
    "PW_Gradient", "EW_Gradient",
    # Quality indicator of the detection quality
    "Quality"
]
mitx_lpid_vars = [
    # As above
    "Counter", "Latitude_QD", "Longitude_QD", "MLT_QD", "L_value", "SZA", "Ne", "Te",
    # Identifier to mark the type of the detected point (see below)
    "PointType",
    # Detection quality of each position
    "Position_Quality"
]

PointType is not present within the source data files, but is identified from the *_ID columns, and has values as follows:

Value

Hex.

Bin.

Meaning

0

0x0

0b0000

LP MIT equatorward edge of the equatorward wall

1

0x1

0b0001

LP MIT poleward edge of the equatorward wall

2

0x2

0b0010

LP MIT equatorward edge of poleward wall

3

0x3

0b0011

LP MIT poleward edge of the poleward boundary

4

0x4

0b0100

LP SETE equatorward bounding position

5

0x5

0b0101

LP SETE poleward bounding position

6

0x6

0b0110

LP Te peak position

MITx_LP example#

start = dt.datetime(2016, 1, 1)
end = dt.datetime(2016, 1, 8)
request = SwarmRequest()
request.set_collection("SW_OPER_MITA_LP_2F")
request.set_products(measurements=mitx_lp_vars, auxiliaries=["QDLat", "MLT"])
data = request.get_between(
    start_time=start, end_time=end, asynchronous=False, show_progress=False
)
ds = data.as_xarray()

Oops! I made a mistake with loading the “units” metadata (the PRISM products diverge from the conventional naming). Here’s a temporary fix (to be fixed in next version of viresclient).

with data.contents[0].open_cdf() as cdf:
    for data_var in ds.data_vars:
        units = cdf.varattsget(data_var).get("UNIT", "-")
        ds[data_var].attrs["units"] = units
ds
<xarray.Dataset>
Dimensions:       (Timestamp: 155, Quality_dim1: 8, Counter_dim1: 2)
Coordinates:
  * Timestamp     (Timestamp) datetime64[ns] 2016-01-01T00:40:13.696000 ... 2...
Dimensions without coordinates: Quality_dim1, Counter_dim1
Data variables: (12/21)
    Spacecraft    (Timestamp) object 'A' 'A' 'A' 'A' 'A' ... 'A' 'A' 'A' 'A' 'A'
    PW_Gradient   (Timestamp) float64 0.3081 0.0938 0.3594 ... 0.2485 0.1623
    Quality       (Timestamp, Quality_dim1) int8 3 1 3 2 3 -1 2 ... 0 0 3 1 3 1
    Longitude     (Timestamp) float64 -102.9 65.6 -126.2 ... 142.1 -47.5 71.85
    Ne            (Timestamp) float64 1.525e+04 1.552e+04 ... 9.107e+03
    Counter       (Timestamp, Counter_dim1) uint32 11804 1 11804 2 ... 1 11911 2
    ...            ...
    MLT           (Timestamp) float64 17.11 5.145 16.81 ... 4.273 18.06 4.416
    DR            (Timestamp) float64 12.18 30.95 24.98 ... 27.9 35.42 42.99
    EW_Gradient   (Timestamp) float64 0.5532 0.1231 0.4566 ... 0.2111 0.1668
    Te            (Timestamp) float64 3.326e+03 3.703e+03 ... 3.247e+03
    QDLat         (Timestamp) float64 55.82 47.91 55.89 ... 58.0 66.72 58.12
    Radius        (Timestamp) float64 6.82e+06 6.819e+06 ... 6.818e+06 6.817e+06
Attributes:
    Sources:         ['SW_OPER_MITA_LP_2F_20160101T000000_20161231T235959_0201']
    MagneticModels:  []
    AppliedFilters:  []
request = SwarmRequest()
request.set_collection("SW_OPER_MITA_LP_2F:ID")
request.set_products(measurements=mitx_lpid_vars, auxiliaries=["QDLat", "MLT"])
data_id = request.get_between(
    start_time=start, end_time=end, asynchronous=False, show_progress=False
)
ds_id = data_id.as_xarray()
# temporary fix again
with data_id.contents[0].open_cdf() as cdf:
    for data_var in ds_id.data_vars:
        units = cdf.varattsget(data_var).get("UNIT", "-")
        ds_id[data_var].attrs["units"] = units
ds_id
<xarray.Dataset>
Dimensions:           (Timestamp: 944, Counter_dim1: 2)
Coordinates:
  * Timestamp         (Timestamp) datetime64[ns] 2016-01-01T00:39:36.696000 ....
Dimensions without coordinates: Counter_dim1
Data variables: (12/16)
    Spacecraft        (Timestamp) object 'A' 'A' 'A' 'A' 'A' ... 'A' 'A' 'A' 'A'
    Longitude         (Timestamp) float64 -103.0 -103.0 -102.9 ... 72.34 72.37
    Ne                (Timestamp) float64 2.144e+05 1.914e+05 ... 2.593e+04
    Counter           (Timestamp, Counter_dim1) uint32 11804 1 11804 ... 11911 2
    L_value           (Timestamp) float64 3.023 3.046 3.353 ... 3.34 3.111 3.064
    Position_Quality  (Timestamp) int8 3 3 3 3 3 3 3 1 2 3 ... 3 3 3 3 3 3 3 2 3
    ...                ...
    Latitude_QD       (Timestamp) float64 53.48 53.64 55.6 ... 55.53 54.09 53.77
    PointType         (Timestamp) uint8 4 0 1 2 6 5 3 5 3 ... 2 3 3 2 5 6 1 0 4
    Te                (Timestamp) float64 2.023e+03 2.113e+03 ... 2.227e+03
    QDLat             (Timestamp) float64 53.48 53.64 55.6 ... 55.53 54.09 53.77
    Radius            (Timestamp) float64 6.82e+06 6.82e+06 ... 6.818e+06
    MLT               (Timestamp) float64 17.11 17.11 17.11 ... 4.434 4.435
Attributes:
    Sources:         ['SW_OPER_MITA_LP_2F_20160101T000000_20161231T235959_0201']
    MagneticModels:  []
    AppliedFilters:  []

Visualisation#

Some visualisation examples will be added here soon. For now, refer to: