FOXES / data /convert_aia.py
griffingoodwin04's picture
refactiring rest of code base and adding checkpoints
dc04e07
Raw
History Blame Contribute Delete
4.76 kB
"""
Convert raw AIA FITS files into paired, brightest-pixel-patched 512x512 .npy
stacks (one file per timestamp, one channel per wavelength) using itipy.
Called by build_dataset.py — not meant to be run standalone.
"""
import collections.abc
import os
from multiprocessing import Pool
collections.Iterable = collections.abc.Iterable # type: ignore[attr-defined]
collections.Mapping = collections.abc.Mapping # type: ignore[attr-defined]
collections.MutableSet = collections.abc.MutableSet # type: ignore[attr-defined]
collections.MutableMapping = collections.abc.MutableMapping # type: ignore[attr-defined]
import numpy as np
from itipy.data.dataset import StackDataset, get_intersecting_files, AIADataset
from itipy.data.editor import BrightestPixelPatchEditor
from tqdm import tqdm
class AIAStackDataset(StackDataset):
"""
Multi-wavelength AIA dataset: stacks one itipy AIADataset per wavelength
so each sample is a single (n_wavelengths, H, W) array.
Args:
data: Data
patch_shape (tuple): Patch shape
wavelengths (list): List of wavelengths
resolution (int): Resolution
ext (str): File extension
**kwargs: Additional arguments
"""
def __init__(self, data, patch_shape=None, wavelengths=None, resolution=512, ext='.fits', allow_errors=False, **kwargs):
if isinstance(data, list):
paths = data
else:
paths = get_intersecting_files(data, wavelengths, ext=ext, **kwargs)
ds_mapping = {94: AIADataset, 131: AIADataset, 171: AIADataset, 193: AIADataset, 211: AIADataset,
304: AIADataset, 335: AIADataset, 1600: AIADataset, 1700: AIADataset, 4500: AIADataset, 6173: AIADataset}
data_sets = [ds_mapping[wl_id](files, wavelength=wl_id, resolution=resolution, ext=ext, allow_errors=allow_errors)
for wl_id, files in zip(wavelengths, paths)] # type: ignore[attr-defined]
super().__init__(data_sets, **kwargs)
if patch_shape is not None:
self.addEditor(BrightestPixelPatchEditor(patch_shape))
_aia_dataset = None
_output_folder = None
def _init_worker(dataset, out_folder):
global _aia_dataset, _output_folder
_aia_dataset = dataset
_output_folder = out_folder
def save_sample(i):
try:
data = _aia_dataset[i] # type: ignore[attr-defined]
file_path = os.path.join(_output_folder, _aia_dataset.getId(i)) + '.npy' # type: ignore[attr-defined]
np.save(file_path, data)
except Exception as e:
print(f"Warning: Could not process sample {i} (ID: {_aia_dataset.getId(i)}): {e}") # type: ignore[attr-defined]
def check_existing_files(base_input_folder, wavelengths, output_folder):
"""Check how many files already exist without loading the full dataset."""
files = get_intersecting_files(base_input_folder, wavelengths, ext='.fits')
if not files or len(files) == 0:
return 0, 0
existing_count = 0
total_expected = len(files[0])
for i in range(total_expected):
first_wl_file = files[0][i]
base_name = os.path.splitext(os.path.basename(first_wl_file))[0]
if '_' in base_name:
base_name = '_'.join(base_name.split('_')[:-1])
output_path = os.path.join(output_folder, base_name) + '.npy'
if os.path.exists(output_path):
existing_count += 1
return existing_count, total_expected
def process_aia_to_npy(input_folder, output_folder, wavelengths):
"""Convert raw AIA FITS files in input_folder into paired 512x512 .npy stacks in output_folder."""
os.makedirs(output_folder, exist_ok=True)
existing_files, total_expected = check_existing_files(input_folder, wavelengths, output_folder)
print(f"Found {existing_files} existing files out of {total_expected} expected files")
if existing_files >= total_expected:
print("All files already processed. Nothing to do.")
return
print(f"Need to process {total_expected - existing_files} remaining files")
aia_dataset = AIAStackDataset(data=input_folder, wavelengths=wavelengths, resolution=512, allow_errors=True)
unprocessed_indices = [
i for i in range(len(aia_dataset))
if not os.path.exists(os.path.join(output_folder, aia_dataset.getId(i)) + '.npy')
]
print(f"Processing {len(unprocessed_indices)} unprocessed samples")
if not unprocessed_indices:
print("All samples already processed. Nothing to do.")
return
with Pool(processes=os.cpu_count(), initializer=_init_worker, initargs=(aia_dataset, output_folder)) as pool:
list(tqdm(pool.imap(save_sample, unprocessed_indices), total=len(unprocessed_indices)))
print("AIA data processing completed.")