API Reference¶
Use Getting Started for examples. The reference below reads signatures, defaults, and docstrings directly from the code. Each definition links to its source.
The API is a short pipeline, and this page follows it in order:
Step |
Use |
You get |
|---|---|---|
1. Get data |
|
|
2. Load a model |
||
3. Predict |
||
4. Look at the results |
attributes and |
numbers and figures |
The AIA, HARP, and SXR processors at the end are the building blocks the fetcher uses; most people won’t need them directly.
Fetch everything you need for a prediction at a given time. |
|
One processed AIA stack, with its metadata and any HARP or GOES data. |
|
Load a folder of saved observations, one at a time. |
|
A FOXES model loaded from a checkpoint, ready to make predictions. |
|
What the model predicts for one AIA stack. |
|
A set of predictions over time, for light curves. |
|
Download AIA images and turn them into a stack the model can use. |
|
Look up HMI active regions (HARPs) and place their boxes on an AIA crop. |
|
Fetch measured GOES X-ray flux to compare against predictions. |
|
Parse a date/time and return it as a timezone-aware UTC datetime. |
1. Get Data¶
ObservationFetcher¶
- class helio_foxes.ObservationFetcher(*, email=None, include_aia=True, include_harps=True, include_sxr=True, resolution=512, aia_tolerance=120, n_workers=4, harp_bbox_expansion=0.0, sxr_tolerance=120, sxr_satellite=None)[source]¶
Fetch everything you need for a prediction at a given time.
This is the usual starting point.
fetch()returns anObservationandfetch_range()yields one per time; pass them toFOXESModelto predict. It wrapsAIAProcessor,HARPProcessor, andSXRProcessorand bundles what they return into anObservation. All three sources are on by default. Any of them can be turned off here or for a single call.The sources fail differently. If the AIA download or processing fails, you get an error, since there’s nothing to predict on. HARP and GOES are extras: if they fail you get an empty region list or
sxr_data=Noneand the observation still comes back. A source you turned off shows up asNone(aia_data=Nonefor AIA,harp_regions=Nonefor HARPs).Set up the data sources.
- Parameters:
email (str or None, optional) – Your registered JSOC email, used for both AIA and HARP queries. Defaults to the
JSOC_EMAILenvironment variable.include_aia (bool, default True) – Which sources to fetch by default. Each fetch call can override these.
include_harps (bool, default True) – Which sources to fetch by default. Each fetch call can override these.
include_sxr (bool, default True) – Which sources to fetch by default. Each fetch call can override these.
resolution (int, default 512) – Processed AIA image size in pixels. Should match the checkpoint.
aia_tolerance (int, default 120) – How far, in seconds, each AIA frame can be from the requested time.
n_workers (int, default 4) – Number of parallel AIA download threads.
harp_bbox_expansion (float, default 0.0) – Fraction of each HARP box’s width and height added on every side (0.1 grows each side by 10%). HARP flux sums use the expanded boxes.
sxr_tolerance (float, default 120) – How far, in seconds, a GOES sample can be from the requested time.
sxr_satellite (int or None, optional) – Use only this GOES satellite (e.g.
18).Noneaverages all satellites with good data.
- fetch(time, *, include_aia=None, include_harps=None, include_sxr=None) Observation[source]¶
Fetch one observation.
Raw downloads are deleted before the method returns. The HARP and GOES data stay attached to the observation, so they show up again when you predict and plot.
- Parameters:
time (datetime.datetime, datetime.date, numpy.datetime64, or str) – Any format
parse_timestamp()accepts.include_aia (bool or None, optional) – Turn a source on or off for this call only.
Nonekeeps the fetcher’s default. You need AIA to make a prediction.include_harps (bool or None, optional) – Turn a source on or off for this call only.
Nonekeeps the fetcher’s default. You need AIA to make a prediction.include_sxr (bool or None, optional) – Turn a source on or off for this call only.
Nonekeeps the fetcher’s default. You need AIA to make a prediction.
- Returns:
Observation
- fetch_range(start, end, *, cadence='1h', on_error='raise', save_dir=None, overwrite=False, progress=False, include_aia=None, include_harps=None, include_sxr=None)[source]¶
Fetch observations over a time range, one at a time.
This is a generator, so nothing gets downloaded until you start looping over it (or hand it to
FOXESModel.predict_time_series()). Only one AIA stack is held in memory at a time, which keeps long ranges manageable.Which times. The range starts at
startand steps forward bycadence.endis included only if it falls exactly on one of those steps. There’s no interpolation, so two requested times close together can end up using the same AIA exposure.How it downloads. AIA frames for the whole range are found with a single JSOC query, then downloaded. HARP and GOES are still queried separately for each time. Very long ranges can produce large JSOC responses, so it’s worth splitting them into chunks.
Saving and reusing. With
save_dirset, each observation is saved withObservation.save()before it’s yielded. On a later run, any time that already has a file is loaded from disk, with no downloads or queries, and only the missing times are fetched. Saved files are reused exactly as they are, so if you change preprocessing or source settings, passoverwrite=Trueto fetch everything again. Reload a saved folder without the fetcher usingload_observations().Errors. By default an AIA failure stops the iterator. With
on_error="skip", the failure is logged with its time and the iterator carries on. HARP and GOES failures never stop it (seefetch()). Problems with the initial JSOC query, or with reading or writing saved files, always raise.- Parameters:
start (datetime.datetime, datetime.date, numpy.datetime64, or str) – First and last times, in any format
parse_timestamp()accepts.endcan’t be beforestart.end (datetime.datetime, datetime.date, numpy.datetime64, or str) – First and last times, in any format
parse_timestamp()accepts.endcan’t be beforestart.cadence (str, datetime.timedelta, pandas.Timedelta, int, or float, default "1h") – Time between observations, as a whole number of seconds. Use a pandas-style string like
"12min", a timedelta, or a plain number of seconds (so720is 12 minutes).on_error ({"raise", "skip"}, default "raise") – What to do when a single time fails to download or process.
save_dir (str or pathlib.Path or None, optional) – Folder to save observations in and reuse them from.
overwrite (bool, default False) – Fetch every time again and replace any saved files.
progress (bool, default False) – Show a tqdm progress bar for the JSOC query and downloads, or for loading files if everything is already saved. If AIA is turned off, it tracks the HARP and GOES fetches instead.
include_aia (bool or None, optional) – Turn a source on or off for this range only, as in
fetch().Nonekeeps the fetcher’s default.include_harps (bool or None, optional) – Turn a source on or off for this range only, as in
fetch().Nonekeeps the fetcher’s default.include_sxr (bool or None, optional) – Turn a source on or off for this range only, as in
fetch().Nonekeeps the fetcher’s default.
- Yields:
Observation – One per successful time, in time order.
Examples
>>> observations = fetcher.fetch_range( ... "2023-08-01 00:00", "2023-08-01 01:00", cadence="12min", ... save_dir="saved_observations", progress=True, ... ) >>> series = model.predict_time_series(observations)
Observation¶
- class helio_foxes.Observation(metadata: ObservationMetadata, aia_data: ndarray | None, sxr_data: dict | None = None, harp_regions: list[dict] | None = None)[source]¶
One processed AIA stack, with its metadata and any HARP or GOES data.
You’ll usually get these from
ObservationFetcher, or build one from your own array withfrom_array(). Pass it toFOXESModel.predict()to get aPrediction.- Parameters:
metadata (ObservationMetadata) – Time, channel order, and crop geometry for
aia_data.aia_data (array-like or None) – Channel-first
(C, H, W)array matchingmetadata.image_shape.Noneif AIA fetching was turned off.from_array()checks the values and converts them to float32; this constructor doesn’t.sxr_data (dict or None, optional) – Measured GOES flux from
SXRProcessor.fetch(), withxrsa_fluxandxrsb_fluxin W/m². It’s only there for comparison; the model never sees it.Noneif SXR was turned off or no data was available.harp_regions (list of dict or None, optional) – Active-region boxes. Each dict needs a
HARPNUM(orharpnum) andtop_pct,left_pct,width_pct, andheight_pct, given as percentages of this crop measured from its top-left corner. For example{"HARPNUM": 1234, "top_pct": 10, "left_pct": 20, "width_pct": 15, "height_pct": 12}.Nonemeans HARPs were never requested. An empty list means they were requested but nothing usable came back, which includes failed queries. Prediction won’t query HARPs for you.
- classmethod from_array(aia_data, *, timestamp, wavelengths=(94, 131, 171, 193, 211, 304, 335), padding_factor=0.1, sxr_data=None, harp_regions=None)[source]¶
Wrap an AIA stack you’ve already preprocessed.
The array is used as is. Nothing is downloaded, and there’s no calibration, cropping, resizing, or normalization, so the stack needs to match the training preprocessing already. The model checks shape and channel order when you run it.
- Parameters:
aia_data (array-like) – Finite numeric
(C, H, W)stack, usually(7, 512, 512). A NumPy array or nested lists both work. Channels-last arrays aren’t transposed for you. The observation stores a float32 copy.timestamp (datetime.datetime, datetime.date, numpy.datetime64, or str) – Required. Any format
parse_timestamp()accepts.wavelengths (sequence of int, optional) – Wavelength of each channel in Ångströms. Prediction needs the default
(94, 131, 171, 193, 211, 304, 335).padding_factor (float, default 0.1) – Padding past the solar limb used when the stack was cropped.
sxr_data (dict or None, optional) – Measured GOES flux; see
Observation.harp_regions (list of dict or None, optional) – Active-region boxes in percent of this crop; see
Observation.
- Returns:
Observation
- save(path, *, overwrite=False)[source]¶
Save the whole observation to a compressed
.npzfile.The file holds the array (if there is one) and the metadata: time, crop geometry, channel order, HARP regions, and SXR data. Reload it with
load()and it’s ready to predict on, with no need to preprocess or normalize it again. The data is saved exactly as is, and pickle isn’t used.The file is written to a temporary name first and only moved into place once it’s complete, so an interrupted save won’t leave a half-written archive behind.
- Parameters:
path (str or pathlib.Path) – Destination ending in
.npz. Missing parent folders are created and~is expanded.overwrite (bool, default False) – Replace an existing file. If False and the file already exists, raises
FileExistsError.
- Returns:
pathlib.Path – Where the archive was written.
- classmethod load(path)[source]¶
Reload an observation written by
save().Existing saved observations load into
aia_dataandsxr_datawithout conversion.- Parameters:
path (str or pathlib.Path) – A
.npzarchive fromsave(). For a plain.npyarray, useObservation.from_array(np.load(path), timestamp=...).- Returns:
Observation – The saved array and metadata, along with any HARP and SXR data.
ObservationMetadata¶
- class helio_foxes.api.ObservationMetadata(timestamp: datetime | str, image_shape: tuple[int, int, int], wavelengths: tuple[int, ...] = (94, 131, 171, 193, 211, 304, 335), padding_factor: float = 0.1, harp_bbox_expansion: float = 0.0)[source]¶
Time, channel order, and crop geometry for one processed AIA stack.
The metadata travels with an observation through prediction and plotting, so HARP boxes can be drawn in the right place later on.
- Parameters:
timestamp (datetime.datetime, datetime.date, numpy.datetime64, or str) – The time you asked for, in any format
parse_timestamp()accepts. Each channel’s actual exposure time can differ slightly.image_shape (sequence of three positive int) – Array shape in channel-first order, e.g.
(7, 512, 512). If AIA fetching was turned off, this is the shape the crop would have had.wavelengths (sequence of int, optional) – Wavelength of each channel in Ångströms, in array order. Prediction needs the default
(94, 131, 171, 193, 211, 304, 335).padding_factor (float, default 0.1) – How far the crop extends past the solar limb, as a fraction of the solar radius. Please keep it consistent with the crop used to train the model (0.1).
harp_bbox_expansion (float, default 0.0) – Fraction of each HARP box’s width and height added on every side, so 0.1 grows each side by 10%. Stored here so HARPs fetched later, at plotting time, get the same expansion.
load_observations¶
- helio_foxes.load_observations(directory, *, progress=False)[source]¶
Load a folder of saved observations, one at a time.
Files are read in filename order. The names that
ObservationFetcher.fetch_range()writes are timestamps, so that’s chronological order. Only one file is in memory at a time, so you can pass the result straight toFOXESModel.predict_time_series():series = model.predict_time_series(load_observations("saved_observations"))
Raises
FileNotFoundErrorif the folder is missing or has no.npzfiles. A broken archive raises an error rather than being skipped.- Parameters:
directory (str or pathlib.Path) – Folder of
.npzfiles written byObservation.save().~is expanded. Every.npzfile in the folder is loaded, so keep normalization files and other archives somewhere else.progress (bool, default False) – Show a tqdm progress bar.
- Yields:
Observation
2. Load a Model and Predict¶
FOXESModel¶
- class helio_foxes.FOXESModel(checkpoint='uncertainty', *, device='auto', legacy_correction_enabled=None, legacy_cutoff='2016-11-19')[source]¶
A FOXES model loaded from a checkpoint, ready to make predictions.
Loading takes a while, so do it once and reuse the model:
model = FOXESModel() # the current uncertainty model result = model.predict(observation)
Give
predict()anObservationto get aPrediction, or givepredict_time_series()many of them to get aPredictionTimeSeries.- Parameters:
checkpoint (str or pathlib.Path, default "uncertainty") – A released checkpoint name or a path to a checkpoint file. The names are
"uncertainty"(the current model) and the legacy"inverted-attention-mask","localized-attention-mask", and"no-attention-mask". A named checkpoint is downloaded the first time you use it and cached in~/.cache/helio_foxes(set theHELIO_FOXES_CACHEenvironment variable to use another folder). If a file with that name exists, the file wins.~is expanded in paths.device ({"auto", "cpu", "cuda", "mps"}, default "auto") – Where to run the model.
"auto"uses a GPU if one is available.legacy_correction_enabled (bool or None, default None) – Turn on the approximate correction for the old deterministic checkpoints: flux (full-disk and per patch) is multiplied by 0.7 for times before
legacy_cutoff.Noneturns it on for the legacy checkpoint names and off for everything else, including file paths, so passTrueif you load a legacy checkpoint from a file. Keep it off forUncertaintyModel.ckptand any model trained on the corrected targets. The weights and normalization themselves aren’t changed.legacy_cutoff (datetime.datetime or str, default "2016-11-19") – Predictions before this UTC time get the 0.7 factor. It’s a rough stand-in for the change in GOES satellites, not a fitted calibration.
- predict_time_series(observations, *, snapshot_time=None, snapshot_wavelength=193)[source]¶
Run the model over a sequence of observations.
Observations are processed one at a time as the iterable is consumed, so this works well with generators like
ObservationFetcher.fetch_range()andload_observations(). The input stacks aren’t kept. If any prediction fails, the error is raised.Those generators can only be looped over once. If you pass one that has already been used, you get an empty series and a warning. Call
ObservationFetcher.fetch_range()again, or turn it into a list first if you need the observations more than once.If you pass
snapshot_time, one AIA channel from the observation closest to that time is kept (the earlier one wins a tie), soPredictionTimeSeries.plot_light_curves()can show it withshow_snapshot=True.- Parameters:
observations (iterable of Observation) – A list, tuple, or generator of observations. Wrap plain arrays with
Observation.from_array()first.snapshot_time (datetime.datetime, datetime.date, numpy.datetime64, str, or None) – Time to keep a snapshot image for, in any format
parse_timestamp()accepts.Nonekeeps no image.snapshot_wavelength (int, default 193) – Which AIA channel to keep, given as a wavelength in Ångströms (e.g.
171), not as an index.
- Returns:
PredictionTimeSeries
- predict(observation)[source]¶
Predict the full-disk flux and per-patch flux map for one observation.
- Parameters:
observation (Observation) – From
ObservationFetcher,load_observations(), orObservation.from_array()(for your own preprocessed arrays). Its AIA stack has to be(7, H, W)with channels in the order 94, 131, 171, 193, 211, 304, 335 Å, andHandWhave to match the checkpoint (512 × 512 for the current one). Its metadata and HARPs are carried over to the result. Its measured GOES XRS-B flux becomes the result’sground_truth.- Returns:
Prediction
- Raises:
TypeError – If
observationisn’t anObservation.ValueError – If the observation has no AIA data, the shape or channel order doesn’t match the checkpoint, or the array has non-finite values.
3. Results and Plotting¶
Prediction¶
- class helio_foxes.Prediction(total_flux: float, flux_map: ndarray, prediction_intervals: dict[str, tuple[float, float]] | None = None, flux_std_map: ndarray | None = None, harp_contributions: list[dict] | None = None, ground_truth: float | None = None, *, metadata: ObservationMetadata | None = None, legacy_correction_enabled: bool = False, flux_scale_factor: float = 1.0)[source]¶
What the model predicts for one AIA stack.
Returned by
FOXESModel.predict(). Read the numbers from the attributes below, or draw them withplot_flux_map()andplot_uncertainty_map().total_fluxis the prediction andground_truthis the matched measured GOES XRS-B flux. All fluxes are in W/m², for the 1–8 Å band.The Gaussian checkpoint assigns a variance contribution to each patch.
flux_std_mapcontains their square roots; the squares add to the full-disk variance. Each HARP’sflux_stdis the square root of the summed variance contributions inside its box. These are model-assigned uncertainty attributions; calibration against individual regional X-ray measurements hasn’t been established.- metadata¶
Metadata from the input observation, kept so HARP boxes can be drawn later. The input array itself isn’t kept.
- Type:
ObservationMetadata or None
- total_flux¶
Predicted full-disk soft X-ray flux.
- Type:
float
- flux_map¶
2D map of each patch’s contribution to
total_flux. It’s on the model’s patch grid (64 × 64 for the current checkpoint), not at image resolution.- Type:
numpy.ndarray
- prediction_intervals¶
{"68": (low, high), "95": (low, high)}nominal full-disk prediction intervals in W/m². They are asymmetric because the Gaussian is defined in normalized log-flux space.Nonefor deterministic checkpoints.- Type:
dict or None
- flux_std_map¶
2D map of the standard-deviation contributions described above, on the same patch grid as
flux_map.Nonefor deterministic checkpoints. Add variances (squared values), rather than these values.- Type:
numpy.ndarray or None
- harp_contributions¶
One dict per active region. Each has
harpnum, the box position (top_pct,left_pct,width_pct,height_pct), andtotal_flux, the total of the positive patch contributions whose centers fall inside the box. Boxes can overlap, so a patch can count toward more than one region.flux_stdissqrt(sum(flux_std_map**2))over the same patches, orNonefor deterministic checkpoints. The original JSOC columns, including the heliographic longitude and latitude bounds, are kept too.Nonemeans HARPs weren’t fetched; an empty list means none were usable.- Type:
list of dict or None
- ground_truth¶
Matched measured GOES XRS-B flux, for comparison with
total_flux. The sample may be offset from the requested time within the fetcher’s tolerance, and may average multiple satellites. Its provenance is in the input observation’ssxr_data.Noneif no sample is available.- Type:
float or None
- legacy_correction_enabled¶
Whether legacy correction is enabled (see
FOXESModel). This can beTruewith a scale factor of 1.0 after the cutoff.- Type:
bool
- flux_scale_factor¶
Factor that was applied to
total_fluxandflux_map: 0.7 for legacy predictions before the cutoff date, otherwise 1.0. The measuredground_truthvalues are never scaled.- Type:
float
- plot_flux_map(*, ax=None, cmap='inferno', vmin=None, vmax=None, show_harp_boxes=True, harp_regions=None, min_harp_flux=1e-7, harp_label_fontsize=6, show_harp_uncertainty=True, harp_label_offsets=None, harp_label_max_shift=80, aia_image=None, harp_colors=None)[source]¶
Plot the per-patch flux map on a log color scale.
The title shows the predicted full-disk flux (with its uncertainty, for Gaussian checkpoints) and the measured GOES XRS-B flux if it’s available. A plot with
aia_imageset gets no title. Patches with zero or negative flux are left blank.HARP boxes. If the prediction has HARP regions, each one is outlined and labeled with its HARP number and summed flux (and, if available,
±its uncertainty). Colors go by flux rank, brightest first. Labels start just outside a box corner, on the side facing the image center. If labels overlap, the other corners are tried and then small nudges, up toharp_label_max_shift. Any label that moves gets a connector line back to its box. Placement is worked out once when you plot, so replot if you resize the figure a lot. On a crowded map, raisemin_harp_fluxor setharp_label_offsetsby hand.- Parameters:
ax (matplotlib.axes.Axes or None, optional) – Axes to draw on. A new figure is created if omitted.
cmap (str or matplotlib.colors.Colormap, default "inferno") – Colormap name or instance.
vmin (float or None, optional) – Color-scale limits in W/m² (must be positive). Default to the smallest and largest positive values in the map.
vmax (float or None, optional) – Color-scale limits in W/m² (must be positive). Default to the smallest and largest positive values in the map.
show_harp_boxes (bool, default True) – Draw and label the HARP boxes, as described above. Nothing is drawn if there are no regions; plotting never queries JSOC.
harp_regions (list of dict or None, optional) – Regions to draw instead of the prediction’s own, for example from
HARPProcessor.fetch(). Hand-made boxes needHARPNUM(orharpnum) andtop_pct,left_pct,width_pct,height_pctin percent of the crop, from its top-left corner.min_harp_flux (float, default 1e-7) – Hide regions whose summed flux is below this, in W/m². The prediction itself is unchanged.
harp_label_fontsize (float, default 6) – Label font size in points.
show_harp_uncertainty (bool, default True) – Add the
±uncertainty line to labels when the prediction has patch uncertainties.harp_label_offsets (dict or None, optional) –
{harpnum: (dx, dy)}starting offsets in points from the chosen box corner; positivedxmoves right and positivedymoves up. Labels placed this way always get a connector.harp_label_max_shift (float, default 80) – How far, in points, a label can be nudged automatically. Set it to 0 to keep every label at its starting corner. Nudged labels stay outside their box and inside the map. A label that can’t find a clear spot within this distance stays where it started.
aia_image (array-like or None, optional) – A processed 2D AIA channel to show instead of the flux map, with the same HARP boxes and labels. It has to cover exactly the same crop the prediction used. The labels still show predicted flux, not AIA intensity. The image is shown with a linear 1–99 percentile stretch (or
vmin/vmax), pixel axes, and no colorbar.cmap="gray"usually looks best.harp_colors (dict or None, optional) –
{harpnum: color}to set specific region colors, e.g. to match another plot. Any matplotlib color works:"tab:blue","#56B4E9", or(0.2, 0.5, 0.8). Other regions keep their rank colors.
- Returns:
matplotlib.axes.Axes – The map axes. Flux maps also get a colorbar.
- Raises:
ValueError – If the map isn’t a finite 2D array, has no positive values, or the color limits are invalid.
- plot_uncertainty_map(*, ax=None, cmap='magma', vmin=None, vmax=None)[source]¶
Plot
flux_std_mapcontributions with a logarithmic color scale.- Parameters:
ax (matplotlib.axes.Axes or None, optional) – Axes to draw on. A new figure and axes are created if omitted.
cmap (str or matplotlib.colors.Colormap, default "magma") – Colormap name such as “magma”, or a Colormap instance.
vmin (float or None, optional) – Positive limits for the logarithmic color scale in W/m². By default, use the smallest and largest positive values in the map.
vmax (float or None, optional) – Positive limits for the logarithmic color scale in W/m². By default, use the smallest and largest positive values in the map.
- Returns:
matplotlib.axes.Axes – Axes containing the map. Its figure also has an uncertainty colorbar.
- Raises:
ValueError – If the prediction has no uncertainty map (deterministic checkpoints), the map has no positive values, or the color limits are invalid. Nonpositive cells are masked.
PredictionTimeSeries¶
- class helio_foxes.PredictionTimeSeries(predictions: tuple[Prediction, ...], *, snapshot: Observation | None = None)[source]¶
A set of predictions over time, for light curves.
You’ll normally get one from
FOXESModel.predict_time_series(). Times are the requested UTC times. Any time that was skipped during download just won’t appear. When a HARP isn’t present at some time, its light curve has a NaN there rather than a zero. Regional fluxes are computed as inPrediction.- Parameters:
predictions (iterable of Prediction) – Predictions with metadata and no two sharing a timestamp. They’re sorted by time and stored as a tuple.
snapshot (Observation or None, optional) – A single AIA channel, shape
(1, H, W), at one of the prediction times. It’s only used for the image panel inplot_light_curves().
- full_disk_light_curve()[source]¶
Return the full-disk light curve as a DataFrame indexed by UTC time.
Columns are
total_flux(predicted) andground_truth(measured GOES XRS-B, if available), both in W/m². Legacy series also getlegacy_correction_enabledandflux_scale_factorcolumns.
- harp_light_curves()[source]¶
Return one light curve per active region, as
{harpnum: DataFrame}.Each DataFrame is indexed by UTC time and covers every prediction in the series, with
total_fluxandflux_stdcolumns in W/m². If a region isn’t present at a time, or there’s no uncertainty, that value is NaN. Nothing is interpolated or filled with zeros.
- plot_light_curves(*, harpnums=None, ax=None, show_full_disk=False, show_observed=False, show_snapshot=False, snapshot_ax=None, aia_ax=None, show_uncertainty=True, min_peak_flux=0.0, legend='auto')[source]¶
Plot HARP light curves, optionally with the full-disk total and GOES.
Every region in the series is plotted by default. The flux axis is logarithmic, so missing, zero, or negative values leave a gap in the line rather than being clipped to the bottom of the plot. Each HARP keeps the same color even when you filter regions out.
Uncertainty. For Gaussian checkpoints, each region gets a shaded band of ± one
flux_std. A band whose lower edge would fall at or below zero is left out. Deterministic checkpoints get no bands. As inPrediction, these are the model’s uncertainty split across regions, not tested regional error bars.Snapshot panels. With
show_snapshot=True, two panels are added to the right of the curves: the flux map at the snapshot time (fromPrediction.plot_flux_map(), with HARP boxes in the same colors as the curves) and the plain AIA image. A dashed line marks the snapshot time on the curves. You need to have calledpredict_time_series(..., snapshot_time=...)first. The snapshot is the observation closest to that time, with the earlier one winning a tie. Only regions that are selected and present at that time get boxes.- Parameters:
harpnums (iterable of int or None, optional) – Which HARPs to plot, e.g.
[1234, 5678].Noneplots all of them, and[]plots none (useful if you only want the totals). Wrap a single number in a list. Unknown numbers raiseValueError.ax (matplotlib.axes.Axes or None, optional) – Axes for the light curves. If you’re also showing the snapshot and want to supply your own axes, pass all three (
ax,snapshot_ax,aia_ax), all different and in the same figure. Otherwise leave them out and the layout is made for you.show_full_disk (bool, default False) – Add the predicted full-disk flux and the measured GOES XRS-B flux for comparison.
min_peak_fluxdoesn’t hide these.show_observed (bool, default False) – Add the predicted full-disk flux and the measured GOES XRS-B flux for comparison.
min_peak_fluxdoesn’t hide these.show_snapshot (bool, default False) – Add the flux map and AIA image panels described above.
snapshot_ax (matplotlib.axes.Axes or None, optional) – Axes for the flux map and AIA image. See
ax.aia_ax (matplotlib.axes.Axes or None, optional) – Axes for the flux map and AIA image. See
ax.show_uncertainty (bool, default True) – Draw the uncertainty bands, and the ± lines on the snapshot’s HARP labels, where the checkpoint provides them.
min_peak_flux (float, default 0.0) – Hide HARPs whose highest flux over the whole series (not just at the snapshot) is below this value in W/m², e.g.
1e-7. Regions that never have a positive flux are always hidden. This applies to the snapshot labels as well, but it only affects the plot; the data in the series is unchanged.legend ({"auto", "full", "compact", "none"}, default "auto") – Legend placed below the curves.
"full"lists every region."compact"shows a region count plus the comparison-line and marker keys, which is handy when the snapshot already labels the HARPs."auto"picks compact when the snapshot is shown and full otherwise.
- Returns:
matplotlib.axes.Axes – The light-curve axes. The snapshot panels, if any, are in the same figure.
Examples
>>> ax = series.plot_light_curves(show_snapshot=True, ... min_peak_flux=1e-7, legend="compact")
Lower-Level Building Blocks¶
AIAProcessor¶
- class helio_foxes.AIAProcessor(*, email=None, resolution=512, tolerance=120, n_workers=4)[source]¶
Download AIA images and turn them into a stack the model can use.
Each stack has seven channels in the order 94, 131, 171, 193, 211, 304, and 335 Å. Processing uses the same ITI pipeline as training and gives you a channel-first
float32array. Most of the time you’ll wantObservationFetcher, which wraps this class and also fetches HARP and GOES data.- Parameters:
email (str or None, optional) – Your registered JSOC email address. Defaults to the
JSOC_EMAILenvironment variable.resolution (int, default 512) – Height and width of each processed channel, in pixels.
tolerance (int, default 120) – How far, in seconds, each AIA frame can be from the requested time.
n_workers (int, default 4) – Number of parallel download threads.
- WAVELENGTHS = (94, 131, 171, 193, 211, 304, 335)¶
AIA channels in Å, in the order the model expects them.
- fetch(time)[source]¶
Download and process all seven channels for one time.
The raw FITS files go into a temporary folder that’s deleted when the method returns, even if something fails along the way.
- Parameters:
time (datetime.datetime, datetime.date, numpy.datetime64, or str) – Any format
parse_timestamp()accepts.- Returns:
numpy.ndarray –
float32array of shape(7, resolution, resolution)inWAVELENGTHSorder.- Raises:
TypeError – If
timeisn’t a typeparse_timestamp()understands.FileNotFoundError – If any channel has no frame within
toleranceseconds.ValueError – If processing returns the wrong shape or non-finite values.
- process_files(paths)[source]¶
Process AIA FITS files you already have on disk.
This runs the same pipeline as
fetch(), just without the download, and your files are left untouched. Wrap the result withObservation.from_array()to predict on it:paths = [Path("fits") / f"{w}.fits" for w in AIAProcessor.WAVELENGTHS] stack = processor.process_files(paths) observation = Observation.from_array(stack, timestamp="2023-08-01 12:00")
- Parameters:
paths (iterable of str or pathlib.Path) – A list of exactly seven FITS files, one per channel, in
WAVELENGTHSorder. A folder name won’t work here.- Returns:
numpy.ndarray –
float32array of shape(7, resolution, resolution).
HARPProcessor¶
- class helio_foxes.HARPProcessor(*, email=None, resolution=512, padding_factor=0.1, bbox_expansion=0.0)[source]¶
Look up HMI active regions (HARPs) and place their boxes on an AIA crop.
Boxes come from the
hmi.sharp_720sseries on JSOC and are converted to percentages of the processed AIA image, so they line up with the flux map.Configure JSOC access and the AIA crop geometry.
- Parameters:
email (str or None, optional) – Your registered JSOC email address. Defaults to the
JSOC_EMAILenvironment variable.resolution (int, default 512) – Side length of the processed AIA image in pixels.
padding_factor (float, default 0.1) – How far the AIA crop extends past the solar limb, as a fraction of the solar radius.
bbox_expansion (float, default 0.0) – Fraction of each box’s width and height added on every side (0.1 grows each side by 10%). Expanded boxes are clipped to the image.
- fetch(time: datetime | str) list[dict][source]¶
Get the HARP regions closest in time to
time.Uses the nearest HARP record with good-quality regions. Each row keeps the original JSOC columns, including
HARPNUMand the rawNOAA_ARSstring. Regions visible in the crop also gettop_pct,left_pct,width_pct, andheight_pct.HARPs are a nice-to-have, so if the query fails or nothing usable turns up, you get an empty list instead of an error. An invalid timestamp still raises.
- Parameters:
time (datetime.datetime, datetime.date, numpy.datetime64, or str) – Any format
parse_timestamp()accepts. JSOC’s own TAI record times aren’t supported.- Returns:
list of dict
SXRProcessor¶
- class helio_foxes.SXRProcessor(*, tolerance=120, satellite=None)[source]¶
Fetch measured GOES X-ray flux to compare against predictions.
By default the fluxes from every GOES satellite with good data are averaged, the same way the training targets were built (see
data.align_aia_sxr). The average is a plain mean of the physical fluxes, taken before any log scaling.Set up the GOES lookup.
- Parameters:
tolerance (float, default 120) – How far, in seconds, a GOES sample can be from the requested time.
satellite (int or None, optional) – Use only this GOES satellite, given as a number (
18, not"GOES-18").Noneaverages all satellites with good data.
- fetch(time) dict | None[source]¶
Get the measured XRS-A (0.5–4 Å) and XRS-B (1–8 Å) flux near a time.
Finds the GOES sample closest to
timethat has good XRS-B data (quality flag zero and a positive flux), the same selection used for the training targets. If two samples are equally close, the earlier one wins. Only satellites reporting at that exact sample time are averaged. Values are used as the science product reports them, with no interpolation or extra scaling.Like HARPs, GOES data is optional, so a missing sample or failed query returns
Noneinstead of raising. An invalid timestamp still raises.- Parameters:
time (datetime.datetime, datetime.date, numpy.datetime64, or str) – Any format
parse_timestamp()accepts.- Returns:
dict or None –
xrsb_fluxandxrsa_fluxin W/m² (xrsa_fluxisNoneif no satellite had good XRS-A data),timestamp(the actual UTC sample time),time_offset_seconds(sample time minus requested time),satellites(which ones were averaged), andmeasurements(each satellite’s own values).
parse_timestamp¶
- helio_foxes.parse_timestamp(value)[source]¶
Parse a date/time and return it as a timezone-aware UTC datetime.
Every function in FOXES that takes a time runs it through this parser, so the rules here apply everywhere:
A date with no time means midnight.
A time with no timezone is treated as UTC.
For other timezones, give an explicit offset such as
-04:00. Abbreviations other than UTC and GMT (EST, for example) aren’t recognized.
Year-first formats work, and so do written-out month names. All-numeric dates like
01/08/2023are rejected because the day/month order is ambiguous. Unix timestamps, partial dates (“August 2023”), relative dates, and NaT are rejected too.- Parameters:
value (datetime.datetime, datetime.date, numpy.datetime64, or str) – For example
"2023-08-01","2023-08-01T12:00:00Z","2023/08/01 12:00","2023.08.01_12:00:00_UTC","August 1, 2023 12:00 UTC", or"2023-08-01T08:00:00-04:00".- Returns:
datetime.datetime – Timezone-aware UTC time.