Tutorial: Time binning¶
This tutorial will teach you how to time bin variables as an essential processing step.
We will use the loaded variables from the cdf file for the tutorial.
import logging
import sys
from datetime import datetime, timezone
from astropy import units as u
import el_paso as ep
ep.logger.setup_logging()
extraction_infos = [
ep.ExtractionInfo(
result_key="Epoch",
name_or_column="Epoch_Ele",
unit=ep.units.cdf_epoch,
),
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,
),
]
start_time = datetime(2017, 7, 14, tzinfo=timezone.utc)
end_time = datetime(2017, 7, 14, 23, 59, 59, tzinfo=timezone.utc)
file_name_stem = "rbspa_rel04_ect-hope-pa-l3_YYYYMMDD_.{6}.cdf"
ep.download(
start_time,
end_time,
save_path=".",
download_url="https://spdf.gsfc.nasa.gov/pub/data/rbsp/rbspa/l3/ect/hope/pitchangle/rel04/YYYY/",
file_name_stem=file_name_stem,
file_cadence="daily",
method="request",
skip_existing=True,
)
variables = ep.extract_variables_from_files(
start_time, end_time, "daily", data_path=".", file_name_stem=file_name_stem, extraction_infos=extraction_infos
)
variables
[INFO ] 2026-06-05 16:17:27 - el_paso.download:236 - File already exists, skipping download: rbspa_rel04_ect-hope-pa-l3_20170714_v7.4.0.cdf
[INFO ] 2026-06-05 16:17:27 - el_paso.download:34 - download finished in 0.137 seconds
[INFO ] 2026-06-05 16:17:27 - el_paso.extract_variables_from_files:112 - Extracting variables ...
{'Epoch': Variable holding (3940,) data points with metadata: VariableMetadata(unit=Unit("cdf_epoch"), original_cadence_seconds=0, source_files=['rbspa_rel04_ect-hope-pa-l3_20170714_v7.4.0.cdf'], description='', processing_notes='', standard_name=''),
'FEDU': Variable holding (3940, 11, 72) data points with metadata: VariableMetadata(unit=Unit("1 / (keV s sr cm2)"), original_cadence_seconds=0, source_files=['rbspa_rel04_ect-hope-pa-l3_20170714_v7.4.0.cdf'], description='', processing_notes='', standard_name=''),
'xGEO': Variable holding (3940, 3) data points with metadata: VariableMetadata(unit=Unit("km"), original_cadence_seconds=0, source_files=['rbspa_rel04_ect-hope-pa-l3_20170714_v7.4.0.cdf'], description='', processing_notes='', standard_name='')}
Time binning is one essential processing step, you probably want to use for most satellite missions. The function is part of the processing module, which holds functions you can use for processing your variables. The function bin_by_time changes the variables in place to reduce memory, because before time binning, data sizes can be quite big. A new time variable is created with the same cadence as provided as an input to the function.
For every variable, which should be time-binned, you have to provide a corresponding time-bin-method. This dictionary is used as input in the time binning function. If you want to change the start- and end-time of the binning, you should truncate the variables first. This can be done by the truncate() method of variable class.
from datetime import timedelta
import numpy as np
from matplotlib import pyplot as plt
variables["xGEO"].truncate(variables["Epoch"], start_time, start_time + timedelta(hours=3))
variables["FEDU"].truncate(variables["Epoch"], start_time, start_time + timedelta(hours=3))
variables["Epoch"].truncate(variables["Epoch"], start_time, start_time + timedelta(hours=3))
plt.plot(
variables["Epoch"].get_data(ep.units.posixtime),
np.log10(variables["FEDU"].get_data()[:, 5, 10]),
label="Before binning",
)
time_bin_methods = {
"xGEO": ep.TimeBinMethod.NanMean,
"FEDU": ep.TimeBinMethod.NanMedian,
}
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),
)
plt.plot(
binned_time_variable.get_data(ep.units.posixtime),
np.log10(variables["FEDU"].get_data()[:, 5, 10]),
label="After binning",
)
plt.legend()
plt.ylabel("log10 Flux")
[WARNING ] 2026-06-05 16:17:27 - py.warnings:110 - /tmp/ipykernel_1602/387006790.py:12: RuntimeWarning: divide by zero encountered in log10
np.log10(variables["FEDU"].get_data()[:, 5, 10]),
[INFO ] 2026-06-05 16:17:27 - el_paso.processing.bin_by_time:162 - Binning by time...
[WARNING ] 2026-06-05 16:17:28 - py.warnings:110 - /home/docs/checkouts/readthedocs.org/user_builds/el-paso/envs/latest/lib/python3.13/site-packages/el_paso/utils.py:209: UserWarning: Discarding nonzero nanoseconds in conversion.
.to_pydatetime()
[WARNING ] 2026-06-05 16:17:28 - py.warnings:110 - /home/docs/checkouts/readthedocs.org/user_builds/el-paso/envs/latest/lib/python3.13/site-packages/el_paso/processing/bin_by_time.py:88: RuntimeWarning: All-NaN slice encountered
binned_array = np.nanmedian(data, axis=0)
[INFO ] 2026-06-05 16:17:28 - el_paso.processing.bin_by_time:21 - bin_by_time finished in 0.088 seconds
[WARNING ] 2026-06-05 16:17:28 - py.warnings:110 - /tmp/ipykernel_1602/387006790.py:30: RuntimeWarning: divide by zero encountered in log10
np.log10(variables["FEDU"].get_data()[:, 5, 10]),
Text(0, 0.5, 'log10 Flux')