Source code for punchbowl.levelq.f_corona_model
from datetime import UTC, datetime
import numpy as np
from astropy.nddata import StdDevUncertainty
from dateutil.parser import parse as parse_datetime_str
from ndcube import NDCube
from prefect import get_run_logger
from punchbowl.data import NormalizedMetadata
from punchbowl.data.punch_io import load_many_cubes_iterable
from punchbowl.data.wcs import load_quickpunch_mosaic_wcs
from punchbowl.level3.f_corona_model import fill_nans_with_interpolation, model_fcorona_for_cube
from punchbowl.prefect import punch_flow
[docs]
@punch_flow(log_prints=True)
def construct_qp_f_corona_model(filenames: list[str],
clip_factor: float = 3.0,
reference_time: str | None = None,
num_workers: int = 8,
num_loaders: int = 8,
fill_nans: bool = False) -> list[NDCube]:
"""Construct QuickPUNCH F corona model."""
logger = get_run_logger()
if reference_time is None:
reference_time = datetime.now(UTC)
elif isinstance(reference_time, str):
reference_time = parse_datetime_str(reference_time)
trefoil_wcs, trefoil_shape = load_quickpunch_mosaic_wcs()
logger.info("construct_f_corona_background started")
if len(filenames) == 0:
msg = "Require at least one input file"
raise ValueError(msg)
filenames.sort()
data_shape = trefoil_shape
number_of_data_frames = len(filenames)
data_cube = np.empty((number_of_data_frames, *data_shape), dtype=float)
meta_list = []
obs_times = []
logger.info("beginning data loading")
dates = []
n_failed = 0
j = 0
for i, result in enumerate(load_many_cubes_iterable(filenames, allow_errors=True, n_workers=num_loaders)):
if isinstance(result, str):
logger.warning(f"Loading {filenames[i]} failed")
logger.warning(result)
n_failed += 1
if n_failed > 10:
raise RuntimeError(f"{n_failed} files failed to load, stopping")
continue
cube = result
dates.append(cube.meta.datetime)
data_cube[j] = np.where(np.isnan(cube.uncertainty.array), np.nan, cube.data)
j += 1
obs_times.append(cube.meta.datetime.timestamp())
meta_list.append(cube.meta)
if (i + 1) % 50 == 0:
logger.info(f"Loaded {i + 1}/{len(filenames)} files")
# Crop the unused end of the array if we had a few files that errored out
data_cube = data_cube[:j+1]
logger.info("ending data loading")
output_datebeg = min(dates).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3]
output_dateend = max(dates).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3]
reference_xt = reference_time.timestamp()
model_fcorona, _ = model_fcorona_for_cube(obs_times, reference_xt, data_cube,
num_workers=num_workers, clip_factor=clip_factor)
if fill_nans:
model_fcorona = fill_nans_with_interpolation(model_fcorona)
uncertainty = np.sqrt(np.abs(model_fcorona)) / np.sqrt(len(obs_times))
meta = NormalizedMetadata.load_template("CFM", "Q")
meta["DATE"] = datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3]
meta["DATE-AVG"] = reference_time.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3]
meta["DATE-OBS"] = reference_time.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3]
meta["DATE-BEG"] = output_datebeg
meta["DATE-END"] = output_dateend
output_cube = NDCube(data=model_fcorona.squeeze(),
meta=meta,
wcs=trefoil_wcs,
uncertainty=StdDevUncertainty(uncertainty))
return [output_cube]