Skip to content

RBSP

el_paso.recipes.rbsp.process_rbsp_ect_combined.process_rbsp_ect_combined

process_rbsp_ect_combined

Process combined RBSP ECT (REPT/MagEIS) electron flux data into the EL-PASO data standard.

Downloads the daily RBSP ECT combined level-3 electron CDF files for the given time range and satellite, extracts the energy/pitch-angle-resolved flux (FEDU), omni-directional flux (FEDO), and position, time-bins all variables to the given cadence, folds the pitch angles and flux to the [0, 90] degree range, computes magnetic-field-related quantities (B field, equatorial pitch angle, L*, L_m, MLT, InvMu, InvK, etc.) with the given magnetic field model via IRBEM, computes the electron phase space density from FEDU, and saves all resulting variables using the requested saving strategy/strategies.

Parameters:

Name Type Description Default
start_time datetime

Start of the time range to process.

required
end_time datetime

End of the time range to process.

required
sat_str Literal['a', 'b']

RBSP satellite identifier ("a" or "b").

required
mag_field Literal['T89', 'T96', 'TS04', 'OP77']

Magnetic field model used to compute the magnetic-field-related variables.

required
raw_data_path str | Path

Directory where raw CDF files are downloaded to and read from. Defaults to ".".

'.'
processed_data_path str | Path

Directory where the processed output files are written to. Defaults to ".".

'.'
cadence timedelta

Time-binning cadence applied to all variables. Defaults to timedelta(minutes=5).

timedelta(minutes=5)
save_strategy Literal['gfz', 'netcdf', 'both']

Which saving strategy/strategies to use for writing the processed output. Defaults to "netcdf".

'netcdf'
num_cores int

Number of CPU cores used for the magnetic field computations. Defaults to 4.

4
Source code in el_paso/recipes/rbsp/process_rbsp_ect_combined.py
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
def process_rbsp_ect_combined(
    start_time: datetime,
    end_time: datetime,
    sat_str: Literal["a", "b"],
    mag_field: Literal["T89", "T96", "TS04", "OP77"],
    raw_data_path: str | Path = ".",
    processed_data_path: str | Path = ".",
    cadence: timedelta = timedelta(minutes=5),
    save_strategy: Literal["gfz", "netcdf", "both"] = "netcdf",
    num_cores: int = 4,
) -> None:
    """Process combined RBSP ECT (REPT/MagEIS) electron flux data into the EL-PASO data standard.

    Downloads the daily RBSP ECT combined level-3 electron CDF files for the given time range and
    satellite, extracts the energy/pitch-angle-resolved flux (FEDU), omni-directional flux (FEDO),
    and position, time-bins all variables to the given cadence, folds the pitch angles and flux to
    the [0, 90] degree range, computes magnetic-field-related quantities (B field, equatorial
    pitch angle, L*, L_m, MLT, InvMu, InvK, etc.) with the given magnetic field model via IRBEM,
    computes the electron phase space density from FEDU, and saves all resulting variables using
    the requested saving strategy/strategies.

    Args:
        start_time (datetime): Start of the time range to process.
        end_time (datetime): End of the time range to process.
        sat_str (Literal["a", "b"]): RBSP satellite identifier ("a" or "b").
        mag_field (Literal["T89", "T96", "TS04", "OP77"]): Magnetic field model used to compute the
            magnetic-field-related variables.
        raw_data_path (str | Path, optional): Directory where raw CDF files are downloaded to and
            read from. Defaults to ".".
        processed_data_path (str | Path, optional): Directory where the processed output files are
            written to. Defaults to ".".
        cadence (timedelta, optional): Time-binning cadence applied to all variables. Defaults to
            timedelta(minutes=5).
        save_strategy (Literal["gfz", "netcdf", "both"], optional): Which saving strategy/strategies
            to use for writing the processed output. Defaults to "netcdf".
        num_cores (int, optional): Number of CPU cores used for the magnetic field computations.
            Defaults to 4.
    """
    logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))
    logging.getLogger().setLevel(logging.INFO)

    raw_data_path = Path(raw_data_path)
    processed_data_path = Path(processed_data_path)

    file_name_stem = "rbsp" + sat_str + "_ect-elec-L3_YYYYMMDD_.{6}.cdf"

    ep.download(
        start_time,
        end_time,
        save_path=raw_data_path,
        download_url=f"https://rbsp-ect.newmexicoconsortium.org/data_pub/rbsp{sat_str}/ECT/level3/YYYY/",
        file_name_stem=file_name_stem,
        file_cadence="daily",
        method="request",
        skip_existing=True,
    )

    extraction_infos = [
        ep.ExtractionInfo(
            result_key="Epoch",
            name_or_column="Epoch",
            unit=ep.units.cdf_epoch,
        ),
        ep.ExtractionInfo(
            result_key="Energy",
            name_or_column="FEDU_Energy",
            unit=u.keV,
            is_time_dependent=False,
        ),
        ep.ExtractionInfo(
            result_key="Pitch_angle",
            name_or_column="FEDU_Alpha",
            unit=u.deg,
            is_time_dependent=False,
        ),
        ep.ExtractionInfo(
            result_key="FEDU",
            name_or_column="FEDU",
            unit=(u.cm**2 * u.s * u.sr * u.keV) ** (-1),
        ),
        ep.ExtractionInfo(
            result_key="FEDU_quality",
            name_or_column="FEDU_Quality",
            unit=u.dimensionless_unscaled,
        ),
        ep.ExtractionInfo(
            result_key="FEDO",
            name_or_column="FEDO",
            unit=(u.cm**2 * u.s * u.sr * u.keV) ** (-1),
        ),
        ep.ExtractionInfo(
            result_key="xGEO",
            name_or_column="Position",
            unit=u.km,
        ),
    ]

    variables = ep.extract_variables_from_files(
        start_time,
        end_time,
        "daily",
        data_path=raw_data_path,
        file_name_stem=file_name_stem,
        extraction_infos=extraction_infos,
    )

    time_bin_methods = {
        "xGEO": ep.TimeBinMethod.NanMean,
        "Energy": ep.TimeBinMethod.Repeat,
        "FEDU": ep.TimeBinMethod.NanMedian,
        "FEDU_Quality": ep.TimeBinMethod.NanMax,
        "FEDO": ep.TimeBinMethod.NanMedian,
        "Pitch_angle": ep.TimeBinMethod.Repeat,
    }

    binned_time_variable = ep.processing.bin_by_time(
        variables["Epoch"],
        variables=variables,
        time_bin_method_dict=time_bin_methods,
        time_binning_cadence=cadence,
        start_time=start_time,
        end_time=end_time,
    )

    variables["Energy"].apply_thresholds_on_data(lower_threshold=0)

    variables["FEDU"].transpose_data([0, 2, 1])  # making it having dimensions (time, energy, pitch angle)
    ep.processing.fold_pitch_angles_and_flux(variables["FEDU"], variables["Pitch_angle"])

    # not needed anymore
    del variables["Epoch"]

    # Calculate magnetic field variables
    irbem_options = ep.processing.magnetic_field_utils.IrbemOptions()

    variables_to_compute: ep.processing.VariableRequest = [
        ("B_Calc", mag_field),
        ("B_Eq", mag_field),
        ("MLT", mag_field),
        ("R_Eq", mag_field),
        ("Alpha_Eq", mag_field),
        ("L_star", mag_field),
        ("L_m", mag_field),
        ("InvMu", mag_field),
        ("InvK", mag_field),
    ]

    magnetic_field_variables = ep.processing.compute_magnetic_field_variables(
        time_var=binned_time_variable,
        xgeo_var=variables["xGEO"],
        variables_to_compute=variables_to_compute,
        irbem_options=irbem_options,
        num_cores=num_cores,
        pa_local_var=variables["Pitch_angle"],
        energy_var=variables["Energy"],
        particle_species="electron",
    )

    psd_variable = ep.processing.compute_phase_space_density(
        variables["FEDU"], variables["Energy"], particle_species="electron"
    )

    variables_to_save: dict[ep.typing.InternalName, ep.Variable] = {
        "Epoch": binned_time_variable,
        "FEDU": variables["FEDU"],
        "Energy_FEDU": variables["Energy"],
        "Alpha": variables["Pitch_angle"],
        "Alpha_Eq": magnetic_field_variables["Alpha_Eq_" + mag_field],
        "R_Eq": magnetic_field_variables["R_Eq_" + mag_field],
        "MLT": magnetic_field_variables["MLT_" + mag_field],
        "L_m": magnetic_field_variables["L_m_" + mag_field],
        "L_star": magnetic_field_variables["L_star_" + mag_field],
        "B_Calc": magnetic_field_variables["B_Calc_" + mag_field],
        "B_Eq": magnetic_field_variables["B_Eq_" + mag_field],
        "PSD": psd_variable,
        "InvMu": magnetic_field_variables["InvMu_" + mag_field],
        "InvK": magnetic_field_variables["InvK_" + mag_field],
        "Position": variables["xGEO"],
    }

    if save_strategy in ("gfz", "both"):
        strategy = ep.saving_strategies.GFZStrategy(
            processed_data_path,
            "RBSP",
            "rbsp" + sat_str,
            "ect_combined",
            mag_field,
            data_standard=ep.data_standards.GFZStandard(),
        )

    if save_strategy in ("netcdf", "both"):
        strategy = ep.saving_strategies.MonthlyRBStrategy(
            base_data_path=Path(processed_data_path),
            mission="RBSP",
            satellite=f"rbsp{sat_str}",
            instrument="ect_combined",
            mag_field=mag_field,
            file_format="nc",
            data_standard=ep.data_standards.GFZStandard(),
        )

    ep.save(variables_to_save, strategy, start_time, end_time, binned_time_variable, append=True)

el_paso.recipes.rbsp.process_rbsp_efw_emfisis_density_combined.process_efw_emfisis_density_combined

process_efw_emfisis_density_combined

Process and combine RBSP EFW and EMFISIS electron density data.

Downloads and extracts EFW (level-3) and EMFISIS (level-4) density data for the given time range and satellite, time-bins both to a 1-minute cadence, cleans the EMFISIS density by masking out "fpe"-flagged digitizer-type entries, transforms the EFW position from GSE to GEO coordinates using IRBEM, computes magnetic-field-related quantities (MLT, equatorial radial distance, equatorial position) with the given magnetic field model, and maps both the EFW and EMFISIS local densities to the magnetic equator using the Denton-average model. If requested, also loads and time-bins hiss-derived densities and maps those to the equator as well.

Parameters:

Name Type Description Default
start_time datetime

Start of the time range to process.

required
end_time datetime

End of the time range to process.

required
sat_str Literal['a', 'b']

RBSP satellite identifier ("a" or "b").

required
irbem_lib_path str | Path

Path to the compiled IRBEM library, used for coordinate transforms and magnetic field computations.

required
mag_field Literal['T89', 'T96', 'TS04']

Magnetic field model used to compute the magnetic-field-related variables.

required
raw_data_path str | Path

Directory where raw CDF files are downloaded to and read from. Defaults to ".".

'.'
processed_data_path str | Path

Directory where the processed output files would be written to. Defaults to ".".

'.'
num_cores int

Number of CPU cores used for the magnetic field computations. Defaults to 4.

4
add_hiss_derived_densitites bool

If True, also load, time-bin, and map to the equator the hiss-derived density data. Defaults to True.

True
hiss_derived_densities_data_path str | Path

Directory containing the hiss-derived density text files. Defaults to ".".

'.'

Raises:

Type Description
NotImplementedError

Always raised before the processed variables are saved; saving via DensityNetCDFStrategy is not yet implemented.

Source code in el_paso/recipes/rbsp/process_rbsp_efw_emfisis_density_combined.py
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
def process_efw_emfisis_density_combined(
    start_time: datetime,
    end_time: datetime,
    sat_str: Literal["a", "b"],
    irbem_lib_path: str | Path,
    mag_field: Literal["T89", "T96", "TS04"],
    raw_data_path: str | Path = ".",
    processed_data_path: str | Path = ".",
    num_cores: int = 4,
    *,
    add_hiss_derived_densitites: bool = True,
    hiss_derived_densities_data_path: str | Path = ".",
) -> None:
    """Process and combine RBSP EFW and EMFISIS electron density data.

    Downloads and extracts EFW (level-3) and EMFISIS (level-4) density data for the given time
    range and satellite, time-bins both to a 1-minute cadence, cleans the EMFISIS density by
    masking out "fpe"-flagged digitizer-type entries, transforms the EFW position from GSE to GEO
    coordinates using IRBEM, computes magnetic-field-related quantities (MLT, equatorial radial
    distance, equatorial position) with the given magnetic field model, and maps both the EFW and
    EMFISIS local densities to the magnetic equator using the Denton-average model. If requested,
    also loads and time-bins hiss-derived densities and maps those to the equator as well.

    Args:
        start_time (datetime): Start of the time range to process.
        end_time (datetime): End of the time range to process.
        sat_str (Literal["a", "b"]): RBSP satellite identifier ("a" or "b").
        irbem_lib_path (str | Path): Path to the compiled IRBEM library, used for coordinate
            transforms and magnetic field computations.
        mag_field (Literal["T89", "T96", "TS04"]): Magnetic field model used to compute the
            magnetic-field-related variables.
        raw_data_path (str | Path, optional): Directory where raw CDF files are downloaded to and
            read from. Defaults to ".".
        processed_data_path (str | Path, optional): Directory where the processed output files
            would be written to. Defaults to ".".
        num_cores (int, optional): Number of CPU cores used for the magnetic field computations.
            Defaults to 4.
        add_hiss_derived_densitites (bool, optional): If True, also load, time-bin, and map to the
            equator the hiss-derived density data. Defaults to True.
        hiss_derived_densities_data_path (str | Path, optional): Directory containing the
            hiss-derived density text files. Defaults to ".".

    Raises:
        NotImplementedError: Always raised before the processed variables are saved; saving via
            `DensityNetCDFStrategy` is not yet implemented.
    """
    logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))
    logging.getLogger().setLevel(logging.INFO)

    irbem_lib_path = Path(irbem_lib_path)
    raw_data_path = Path(raw_data_path)
    processed_data_path = Path(processed_data_path)

    efw_variables = _get_efw_variables(
        start_time - timedelta(minutes=10), end_time + timedelta(minutes=10), sat_str, raw_data_path
    )
    emfisis_variables = _get_emfisis_variables(
        start_time - timedelta(minutes=10), end_time + timedelta(minutes=10), sat_str, raw_data_path
    )

    efw_time_bin_methods = {
        "xGSE": ep.TimeBinMethod.NanMean,
        "Density": ep.TimeBinMethod.NanMedian,
    }

    binned_time_variable = ep.processing.bin_by_time(
        efw_variables["Epoch"],
        variables=efw_variables,
        time_bin_method_dict=efw_time_bin_methods,
        time_binning_cadence=timedelta(minutes=1),
        start_time=start_time,
        end_time=end_time,
    )

    emfisis_time_bin_methods = {
        "Digi_type": ep.TimeBinMethod.Unique,
        "Density": ep.TimeBinMethod.NanMedian,
    }

    _ = ep.processing.bin_by_time(
        emfisis_variables["Epoch"],
        variables=emfisis_variables,
        time_bin_method_dict=emfisis_time_bin_methods,
        time_binning_cadence=timedelta(minutes=1),
        start_time=start_time,
        end_time=end_time,
    )

    digi_type_cleaned = np.asarray([s.strip() for s in emfisis_variables["Digi_type"].get_data()])
    digi_type_cleaned = digi_type_cleaned.astype("S")
    emfisis_variables["Digi_type"].set_data(digi_type_cleaned, "same")

    datetimes = [datetime.fromtimestamp(t, tz=timezone.utc) for t in binned_time_variable.get_data(ep.units.posixtime)]

    xgeo_data = ep.processing.magnetic_field_utils.Coords(lib_path=irbem_lib_path).transform(
        datetimes,
        efw_variables["xGSE"].get_data(ep.units.RE).astype(np.float64),
        ep.IRBEM_SYSAXIS_GSE,
        ep.IRBEM_SYSAXIS_GEO,
    )

    efw_variables["xGEO"] = ep.Variable(data=xgeo_data, original_unit=ep.units.RE)

    # Calculate magnetic field variables
    irbem_options = ep.processing.magnetic_field_utils.IrbemOptions()

    variables_to_compute: ep.processing.VariableRequest = [
        ("MLT", mag_field),
        ("R_Eq", mag_field),
        ("xGEO_Eq", mag_field),
    ]

    magnetic_field_variables = ep.processing.compute_magnetic_field_variables(
        time_var=binned_time_variable,
        xgeo_var=efw_variables["xGEO"],
        variables_to_compute=variables_to_compute,
        irbem_lib_path=str(irbem_lib_path),
        irbem_options=irbem_options,
        num_cores=num_cores,
    )

    efw_variables["Density_mapped"] = ep.processing.compute_equatorial_plasmaspheric_density(
        efw_variables["Density"],
        efw_variables["xGEO"],
        magnetic_field_variables["xGEO_eq_" + mag_field],
        method="Denton_average",
    )
    emfisis_variables["Density_mapped"] = ep.processing.compute_equatorial_plasmaspheric_density(
        emfisis_variables["Density"],
        efw_variables["xGEO"],
        magnetic_field_variables["xGEO_eq_" + mag_field],
        method="Denton_average",
    )

    if add_hiss_derived_densitites:
        hiss_derived_densities_vars = _get_and_time_bin_hiss_derived_densities(
            hiss_derived_densities_data_path, start_time, end_time, sat_str
        )
        hiss_derived_densities_vars["Density_mapped"] = ep.processing.compute_equatorial_plasmaspheric_density(
            hiss_derived_densities_vars["Density"],
            efw_variables["xGEO"],
            magnetic_field_variables["xGEO_eq_" + mag_field],
            method="Denton_average",
        )

    variables_to_save = {
        "time": binned_time_variable,
        "density_efw_local": efw_variables["Density"],
        "density_emfisis_local": emfisis_variables["Density"],
        "density_efw_eq": efw_variables["Density_mapped"],
        "density_emfisis_eq": emfisis_variables["Density_mapped"],
        "MLT": magnetic_field_variables["MLT_" + mag_field],
        "R_eq": magnetic_field_variables["R_eq_" + mag_field],
        "density_emfisis_digi_type": emfisis_variables["Digi_type"],
        "xGEO": efw_variables["xGEO"],
        "xGEO_eq": magnetic_field_variables["xGEO_eq_" + mag_field],
    }

    if add_hiss_derived_densitites:
        variables_to_save |= {
            "density_hiss_derived_local": hiss_derived_densities_vars["Density"],
            "density_hiss_derived_eq": hiss_derived_densities_vars["Density_mapped"],
        }

    raise NotImplementedError

    saving_strategy = ep.saving_strategies.DensityNetCDFStrategy(
        base_data_path=processed_data_path,
        file_name_stem=f"rbsp_{sat_str}_densities_combined",
        mag_field=mag_field,
        satellite="RBSP",
    )

    ep.save(variables_to_save, saving_strategy, start_time, end_time, binned_time_variable)

el_paso.recipes.rbsp.process_rbsp_emfisis_waves.process_rbsp_emfisis_waves

process_rbsp_emfisis_waves

Process RBSP EMFISIS wave, density, and magnetometer data and save derived wave properties.

Downloads and extracts the EMFISIS WFR spectral-matrix-diagonal data, the EMFISIS density data, the EMFISIS magnetometer data, and the EMFISIS wave-normal-angle (WNA) survey data for the given time range and satellite. The density and magnetometer data are interpolated onto the WFR time grid, the magnetometer data is cleaned using a quality flag, orbital quantities (L-shell, MLAT, MLT, electron cyclotron frequency) are derived from the cleaned magnetometer data, and the total magnetic wave power spectral density is computed from the WFR spectral-matrix components. The wave frequency, frequency bandwidth, wave normal angle, planarity, and ellipticity are saved using DailyWaveStrategy. Finally, diagnostic plots of the density, orbit, magnetometer, WFR spectrogram, and WNA properties are generated and shown or saved to disk.

Parameters:

Name Type Description Default
start_time datetime

Start of the time range to process.

required
end_time datetime

End of the time range to process.

required
sat_str Literal['a', 'b']

RBSP satellite identifier ("a" or "b").

required
raw_data_path str | Path

Base directory where raw CDF files are downloaded to and read from. Defaults to ".".

'.'
processed_data_path str | Path

Directory where the processed output files are written to. Defaults to ".".

'.'
Source code in el_paso/recipes/rbsp/process_rbsp_emfisis_waves.py
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
def process_rbsp_emfisis_waves(
    start_time: datetime,
    end_time: datetime,
    sat_str: Literal["a", "b"],
    raw_data_path: str | Path = ".",
    processed_data_path: str | Path = ".",
) -> None:
    """Process RBSP EMFISIS wave, density, and magnetometer data and save derived wave properties.

    Downloads and extracts the EMFISIS WFR spectral-matrix-diagonal data, the EMFISIS density
    data, the EMFISIS magnetometer data, and the EMFISIS wave-normal-angle (WNA) survey data for
    the given time range and satellite. The density and magnetometer data are interpolated onto
    the WFR time grid, the magnetometer data is cleaned using a quality flag, orbital quantities
    (L-shell, MLAT, MLT, electron cyclotron frequency) are derived from the cleaned magnetometer
    data, and the total magnetic wave power spectral density is computed from the WFR
    spectral-matrix components. The wave frequency, frequency bandwidth, wave normal angle,
    planarity, and ellipticity are saved using `DailyWaveStrategy`. Finally, diagnostic plots of
    the density, orbit, magnetometer, WFR spectrogram, and WNA properties are generated and shown
    or saved to disk.

    Args:
        start_time (datetime): Start of the time range to process.
        end_time (datetime): End of the time range to process.
        sat_str (Literal["a", "b"]): RBSP satellite identifier ("a" or "b").
        raw_data_path (str | Path, optional): Base directory where raw CDF files are downloaded to
            and read from. Defaults to ".".
        processed_data_path (str | Path, optional): Directory where the processed output files are
            written to. Defaults to ".".
    """
    wfr_vars = _get_wfr_data(start_time, end_time, Path(raw_data_path), sat_str)

    target_time_var = wfr_vars["Epoch"]
    density_vars = _get_density_data(start_time, end_time, Path(raw_data_path), sat_str, target_time_var)
    mag_vars = _get_magnetometer_data(start_time, end_time, Path(raw_data_path), sat_str, target_time_var)
    wna_vars = _get_wna_data(start_time, end_time, Path(raw_data_path), sat_str)

    mag_vars = _clean_magnetometer_data(mag_vars)

    orbit_vars = _calculate_orbital_vars(mag_vars)
    psd_var = _compute_total_psd(wfr_vars)

    vars_to_save: dict[ep.typing.InternalName, ep.Variable] = {
        "Epoch": target_time_var,
        "Wave_frequency": wfr_vars["freq"],
        "Wave_frequency_bandwidth": wfr_vars["bandwidth"],
        "Wave_normal_angle": wna_vars["WNA"],
        "Wave_planarity": wna_vars["planarity"],
        "Wave_ellipticity": wna_vars["ellipticity"],
    }

    saving_strat = ep.saving_strategies.DailyWaveStrategy(
        processed_data_path, "RBSP", f"rbsp{sat_str}", "EMFISIS", ep.data_standards.GFZStandard()
    )

    ep.save(vars_to_save, saving_strat, start_time, end_time)

    wfr_vars["BB"] = psd_var

    _plot_density(density_vars)
    orbit_vars["Epoch"] = mag_vars["Epoch"]
    _plot_orbit(orbit_vars)
    _plot_magnetometer(mag_vars)
    _plot_wfr(wfr_vars)
    _plot_wna(wna_vars)

el_paso.recipes.rbsp.process_rbsp_hope_electrons.process_rbsp_hope_electrons

process_rbsp_hope_electrons

Process RBSP ECT/HOPE electron flux data into the EL-PASO data standard.

Downloads the daily RBSP HOPE pitch-angle level-3 electron CDF files for the given time range and satellite, extracts the energy/pitch-angle-resolved flux (FEDU) and position, applies a lower threshold to the flux, time-bins all variables to a 5-minute cadence, folds the pitch angles and flux to the [0, 90] degree range, computes magnetic-field-related quantities (B field, equatorial pitch angle, L*, L_m, MLT, InvMu, InvK, etc.) with the given magnetic field model via IRBEM, computes the electron phase space density from FEDU, and saves all resulting variables using the requested saving strategy/strategies.

Parameters:

Name Type Description Default
start_time datetime

Start of the time range to process.

required
end_time datetime

End of the time range to process.

required
sat_str Literal['a', 'b']

RBSP satellite identifier ("a" or "b").

required
mag_field Literal['T89', 'T96', 'TS04']

Magnetic field model used to compute the magnetic-field-related variables.

required
raw_data_path str | Path

Directory where raw CDF files are downloaded to and read from. Defaults to ".".

'.'
processed_data_path str | Path

Directory where the processed output files are written to. Defaults to ".".

'.'
num_cores int

Number of CPU cores used for the magnetic field computations. Defaults to 32.

32
save_strategy Literal['gfz', 'netcdf', 'both']

Which saving strategy/strategies to use for writing the processed output. Defaults to "netcdf".

'netcdf'
Source code in el_paso/recipes/rbsp/process_rbsp_hope_electrons.py
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
def process_rbsp_hope_electrons(
    start_time: datetime,
    end_time: datetime,
    sat_str: Literal["a", "b"],
    mag_field: Literal["T89", "T96", "TS04"],
    raw_data_path: str | Path = ".",
    processed_data_path: str | Path = ".",
    num_cores: int = 32,
    save_strategy: Literal["gfz", "netcdf", "both"] = "netcdf",
) -> None:
    """Process RBSP ECT/HOPE electron flux data into the EL-PASO data standard.

    Downloads the daily RBSP HOPE pitch-angle level-3 electron CDF files for the given time range
    and satellite, extracts the energy/pitch-angle-resolved flux (FEDU) and position, applies a
    lower threshold to the flux, time-bins all variables to a 5-minute cadence, folds the pitch
    angles and flux to the [0, 90] degree range, computes magnetic-field-related quantities (B
    field, equatorial pitch angle, L*, L_m, MLT, InvMu, InvK, etc.) with the given magnetic field
    model via IRBEM, computes the electron phase space density from FEDU, and saves all resulting
    variables using the requested saving strategy/strategies.

    Args:
        start_time (datetime): Start of the time range to process.
        end_time (datetime): End of the time range to process.
        sat_str (Literal["a", "b"]): RBSP satellite identifier ("a" or "b").
        mag_field (Literal["T89", "T96", "TS04"]): Magnetic field model used to compute the
            magnetic-field-related variables.
        raw_data_path (str | Path, optional): Directory where raw CDF files are downloaded to and
            read from. Defaults to ".".
        processed_data_path (str | Path, optional): Directory where the processed output files are
            written to. Defaults to ".".
        num_cores (int, optional): Number of CPU cores used for the magnetic field computations.
            Defaults to 32.
        save_strategy (Literal["gfz", "netcdf", "both"], optional): Which saving strategy/strategies
            to use for writing the processed output. Defaults to "netcdf".
    """
    raw_data_path = Path(raw_data_path)
    processed_data_path = Path(processed_data_path)

    file_name_stem = "rbsp" + sat_str + "_rel04_ect-hope-pa-l3_YYYYMMDD_.{6}.cdf"

    ep.download(
        start_time,
        end_time,
        save_path=raw_data_path,
        download_url=f"https://spdf.gsfc.nasa.gov/pub/data/rbsp/rbsp{sat_str}/l3/ect/hope/pitchangle/rel04/YYYY/",
        file_name_stem=file_name_stem,
        file_cadence="daily",
        method="request",
        skip_existing=True,
    )

    extraction_infos = [
        ep.ExtractionInfo(
            result_key="Epoch",
            name_or_column="Epoch_Ele",
            unit=ep.units.cdf_epoch,
        ),
        ep.ExtractionInfo(
            result_key="Energy",
            name_or_column="HOPE_ENERGY_Ele",
            unit=u.eV,
        ),
        ep.ExtractionInfo(
            result_key="Pitch_angle",
            name_or_column="PITCH_ANGLE",
            unit=u.deg,
            is_time_dependent=False,
        ),
        ep.ExtractionInfo(
            result_key="FEDU",
            name_or_column="FEDU",
            unit=(u.cm**2 * u.s * u.sr * u.keV) ** (-1),
        ),
        ep.ExtractionInfo(
            result_key="xGEO",
            name_or_column="Position_Ele",
            unit=u.km,
        ),
    ]

    variables = ep.extract_variables_from_files(
        start_time,
        end_time,
        "daily",
        data_path=raw_data_path,
        file_name_stem=file_name_stem,
        extraction_infos=extraction_infos,
    )

    variables["FEDU"].apply_thresholds_on_data(1e-21)

    time_bin_methods = {
        "xGEO": ep.TimeBinMethod.NanMean,
        "Energy": ep.TimeBinMethod.NanMedian,
        "FEDU": ep.TimeBinMethod.NanMedian,
        "Pitch_angle": ep.TimeBinMethod.Repeat,
    }

    binned_time_variable = ep.processing.bin_by_time(
        variables["Epoch"],
        variables=variables,
        time_bin_method_dict=time_bin_methods,
        time_binning_cadence=timedelta(minutes=5),
    )

    variables["FEDU"].transpose_data([0, 2, 1])  # making it having dimensions (time, energy, pitch angle)
    ep.processing.fold_pitch_angles_and_flux(variables["FEDU"], variables["Pitch_angle"])

    # not needed anymore
    del variables["Epoch"]

    # Calculate magnetic field variables
    irbem_options = ep.processing.magnetic_field_utils.IrbemOptions()

    vars_to_compute: ep.typing.VariableRequest = [
        ("B_Calc", mag_field),
        ("MLT", mag_field),
        ("B_Eq", mag_field),
        ("R_Eq", mag_field),
        ("Alpha_Eq", mag_field),
        ("L_star", mag_field),
        ("L_m", mag_field),
        ("InvK", mag_field),
        ("InvMu", mag_field),
    ]

    magnetic_field_variables = ep.processing.compute_magnetic_field_variables(
        time_var=binned_time_variable,
        xgeo_var=variables["xGEO"],
        variables_to_compute=vars_to_compute,
        irbem_options=irbem_options,
        num_cores=num_cores,
        pa_local_var=variables["Pitch_angle"],
        energy_var=variables["Energy"],
        particle_species="electron",
    )

    psd_var = ep.processing.compute_phase_space_density(variables["FEDU"], variables["Energy"], "electron")

    variables_to_save: dict[ep.typing.InternalName, ep.Variable] = {
        "Epoch": binned_time_variable,
        "FEDU": variables["FEDU"],
        "Position": variables["xGEO"],
        "Energy_FEDU": variables["Energy"],
        "Alpha": variables["Pitch_angle"],
        "Alpha_Eq": magnetic_field_variables["Alpha_Eq_" + mag_field],
        "L_star": magnetic_field_variables["L_star_" + mag_field],
        "MLT": magnetic_field_variables["MLT_" + mag_field],
        "L_m": magnetic_field_variables["L_m_" + mag_field],
        "R_Eq": magnetic_field_variables["R_Eq_" + mag_field],
        "InvK": magnetic_field_variables["InvK_" + mag_field],
        "InvMu": magnetic_field_variables["InvMu_" + mag_field],
        "B_Eq": magnetic_field_variables["B_Eq_" + mag_field],
        "B_Calc": magnetic_field_variables["B_Calc_" + mag_field],
        "PSD": psd_var,
    }

    if save_strategy in ("gfz", "both"):
        strategy = ep.saving_strategies.GFZStrategy(
            processed_data_path,
            mission="RBSP",
            satellite="rbsp" + sat_str,
            instrument="hope",
            mag_field=mag_field,
            data_standard=ep.data_standards.GFZStandard(),
        )

    if save_strategy in ("netcdf", "both"):
        strategy = ep.saving_strategies.MonthlyRBStrategy(
            base_data_path=Path(processed_data_path),
            mission="RBSP",
            satellite="rbsp" + sat_str,
            instrument="hope",
            mag_field=mag_field,
            file_format=".nc",
            data_standard=ep.data_standards.GFZStandard(),
        )

    ep.save(variables_to_save, strategy, start_time, end_time, time_var=binned_time_variable, append=True)