Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
681f156
feat(orchestration): the keep list, and the script that acts on it
Sep 1, 2026
de243a8
feat(orchestration): exp_persist, between exp_psf and clean_exposure
Sep 1, 2026
4cf639f
docs(orchestration): exp_persist in the rule list, and why the report…
Sep 1, 2026
1fa6455
feat(orchestration): exp_persist packs one tar per exposure, not loos…
cailmdaley Sep 3, 2026
a14a2f3
fix(orchestration): persist_exp never leaves a .tmp behind on failure
cailmdaley Sep 3, 2026
d91da36
docs(orchestration): drop references to the removed star-catalogue rules
cailmdaley Sep 9, 2026
626aaba
feat(orchestration): the two campaign-level merges
cailmdaley Sep 9, 2026
fc9aa3e
fix(orchestration): seven defects in the campaign-level merges
cailmdaley Sep 9, 2026
d774cc3
fix(create_final_cat): make the merged-catalogue writer reproducible
cailmdaley Sep 9, 2026
98532ce
perf(orchestration): size the two merges from the data, not from a guess
cailmdaley Sep 9, 2026
d0ecfdd
feat(orchestration): persist_exp keeps NAMED products, not globs
cailmdaley Sep 9, 2026
3b8c7d5
perf(merge_starcat): accumulate arrays, not python lists of floats
cailmdaley Sep 9, 2026
0ad6403
feat(orchestration): the star catalogue's inputs are not a user choice
cailmdaley Sep 9, 2026
90dfb00
fix(cfis): two stale columns in final_cat.param, and no mask column a…
cailmdaley Sep 9, 2026
a434c9a
perf(merge_starcat): two passes, so nothing is held twice
cailmdaley Sep 9, 2026
3c29825
feat(orchestration): final_cat_merge reconciles instead of rebuilding
cailmdaley Sep 9, 2026
78d2ce9
fix(orchestration): eight defects found reviewing the merge work
cailmdaley Sep 10, 2026
0fb514b
feat(orchestration): the star catalogue becomes hdf5, reconciled like…
cailmdaley Sep 10, 2026
4ed9fb0
fix(orchestration): nine findings from the third review
cailmdaley Sep 10, 2026
e86d8c8
test(unit): property-based state machines for reconcile and persist_exp
cailmdaley Sep 10, 2026
1a343e6
fix(persist-exp): the PSF run dir is run_sp_exp_SxSePsf
cailmdaley Sep 10, 2026
3e269c4
final_cat_merge, star_cat_merge: record code provenance in the HDF5 a…
cailmdaley Sep 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 44 additions & 21 deletions scripts/python/create_final_cat.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,17 @@ def read_param_file(path, verbose=False):
print("No parameters read", end="")
print(" into merged catalogue")

param_list_unique = list(set(param_list))

# Ordered dedup. list(set(...)) reordered the columns by the process's
# string hash seed, so two runs of this tool over the same inputs produced
# files whose datasets differed in column ORDER — which is part of a
# structured dtype, and therefore part of the file.
param_list_unique = list(dict.fromkeys(param_list))

if verbose:
n = len(param_list) - len(param_list_unique)
if n > 1:
print("Removed {n} duplicate entries")
if n > 0:
print(f"Removed {n} duplicate entries")

return param_list_unique


Expand Down Expand Up @@ -312,16 +316,20 @@ def read_data(fits_file, params):
if params["param_list"] is None:
params["param_list"] = [col for col in data.keys()]

try:
extracted_data = {col: data[col] for col in params["param_list"]}
dtype = data.dtype
except:
print(f"Error for ID {id}, path {fits_file}")
for col in params["param_list"]:
if col not in data:
print(col, end=" ")
print()
continue
# RAISE, do not print and fall through. The bare `except:` this replaces
# left extracted_data and dtype unbound, so the caller's own error was an
# UnboundLocalError from the return statement below, naming neither the
# file nor the column that was actually missing.
present = set(data.dtype.names or ())
missing = [col for col in params["param_list"] if col not in present]
if missing:
raise KeyError(
f"{fits_file}: missing {len(missing)} of the "
f"{len(params['param_list'])} requested column(s): "
f"{' '.join(missing)}"
)
extracted_data = {col: data[col] for col in params["param_list"]}
dtype = data.dtype

return extracted_data, dtype

Expand All @@ -330,16 +338,29 @@ def copy_data(param_list, extracted_data, dtype):
"""Copy Data.

"""
# THE REQUESTED COLUMNS ONLY, IN THE PARAMETER FILE'S ORDER. Two things
# are being fixed here and they are easy to conflate. Allocating with the
# source's full dtype and filling only the requested columns left every
# other column as uninitialised memory — meaningless values, and different
# bytes on every run over the same inputs. And ordering the result by the
# SOURCE catalogue's columns made the output dtype a property of the
# catalogue rather than of the parameter file: two tiles written by
# different ShapePipe versions, whose catalogues order or extend their
# columns differently, then landed in one merged file with two different
# structured dtypes, which np.concatenate refuses. The parameter file is
# the schema; it says which columns AND in what order.
wanted = set(dtype.names or ())
columns = [col for col in param_list if col in wanted]
subset = np.dtype([(col, dtype[col]) for col in columns])

# Initialize new data structure
structured_data = np.empty(
len(extracted_data[param_list[0]]),
dtype=dtype,
dtype=subset,
)

# Loop over parameters
for col in param_list:
if not col in extracted_data:
print(f"Column {col} not in file with ID {id}")
for col in columns:
structured_data[col] = extracted_data[col]

#if isinstance(extracted_data[col][0], (np.ndarray, tuple, list)):
Expand Down Expand Up @@ -467,12 +488,14 @@ def process(params):

structured_data = copy_data(params["param_list"], extracted_data, dtype)

# Create a new dataset
# Create a new dataset. dtype comes from the array copy_data
# built, not from the source catalogue: they differ now that
# copy_data allocates the requested columns alone.
try:
patch_group.create_dataset(
str(id),
data=structured_data,
dtype=dtype,
dtype=structured_data.dtype,
)
except:
print(f"Error for {id}: Could not create dataset in group {patch}")
Expand Down
Loading
Loading