From b70bf8c4c0ed4fa04b85d031518c48e615602f0b Mon Sep 17 00:00:00 2001 From: Jeremy Kubica <104161096+jeremykubica@users.noreply.github.com> Date: Sun, 29 Sep 2024 15:36:16 -0400 Subject: [PATCH] Fix segfault in weighted variance stamps --- src/kbmod/image_collection.py | 10 +++++++++- src/kbmod/search/stamp_creator.cpp | 16 ++++++++++------ .../fits_standardizers/fits_standardizer.py | 4 ++++ 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/kbmod/image_collection.py b/src/kbmod/image_collection.py index 8dc900a36..dce44354d 100644 --- a/src/kbmod/image_collection.py +++ b/src/kbmod/image_collection.py @@ -270,6 +270,10 @@ def fromTargets(cls, tgts, force=None, config=None, **kwargs): of the registered standardizers can be provided. Optionally, provide the `Standardizer` class itself in which case it will be called for each target in the iterable. + config : `~StandardizerConfig`, `dict` or `None`, optional + Standardizer configuration or dictionary containing the config + parameters for standardization. When `None` default values for the + appropriate `Standardizer` will be used. **kwargs : `dict` Remaining keyword arguments are passed to the `Standardizer`. @@ -296,10 +300,14 @@ def fromDir(cls, dirpath, recursive=False, force=None, config=None, **kwargs): recursive : `bool` If the location is a local filesystem directory, scan it recursively including all sub-directories. - forceStandardizer : `Standardizer` or `None` + force : `Standardizer` or `None` If `None`, when applicable, determine the correct `Standardizer` to use automatically. Otherwise force the use of the given `Standardizer`. + config : `~StandardizerConfig`, `dict` or `None`, optional + Standardizer configuration or dictionary containing the config + parameters for standardization. When `None` default values for the + appropriate `Standardizer` will be used. **kwargs : `dict` Remaining kwargs, not listed here, are passed onwards to the underlying `Standardizer`. diff --git a/src/kbmod/search/stamp_creator.cpp b/src/kbmod/search/stamp_creator.cpp index 08c10a2c2..c5d1341af 100644 --- a/src/kbmod/search/stamp_creator.cpp +++ b/src/kbmod/search/stamp_creator.cpp @@ -14,7 +14,7 @@ std::vector StampCreator::create_stamps(ImageStack& stack, const Traje bool keep_no_data, const std::vector& use_index) { if (use_index.size() > 0) assert_sizes_equal(use_index.size(), stack.img_count(), "create_stamps() use_index"); - bool use_all_stamps = use_index.size() == 0; + bool use_all_stamps = (use_index.size() == 0); std::vector stamps; unsigned int num_times = stack.img_count(); @@ -277,7 +277,7 @@ std::vector StampCreator::create_variance_stamps(ImageStack& stack, co int radius, const std::vector& use_index) { if (use_index.size() > 0) assert_sizes_equal(use_index.size(), stack.img_count(), "create_stamps() use_index"); - bool use_all_stamps = use_index.size() == 0; + bool use_all_stamps = (use_index.size() == 0); std::vector stamps; unsigned int num_times = stack.img_count(); @@ -297,22 +297,26 @@ std::vector StampCreator::create_variance_stamps(ImageStack& stack, co RawImage StampCreator::get_variance_weighted_stamp(ImageStack& stack, const Trajectory& trj, int radius, const std::vector& use_index) { + if (radius < 0) throw std::runtime_error("Invalid stamp radius. Must be >= 0."); unsigned int num_images = stack.img_count(); if (num_images == 0) throw std::runtime_error("Unable to create mean image given 0 images."); unsigned int stamp_width = 2 * radius + 1; // Make the stamps for each time step. - std::vector empty_vect; std::vector sci_stamps = create_stamps(stack, trj, radius, true /*=keep_no_data*/, use_index); std::vector var_stamps = create_variance_stamps(stack, trj, radius, use_index); + if (sci_stamps.size() != var_stamps.size()) { + throw std::runtime_error("Mismatched number of stamps returned."); + } + num_images = sci_stamps.size(); // Do the weighted mean. Image result = Image::Zero(stamp_width, stamp_width); - for (int y = 0; y < stamp_width; ++y) { - for (int x = 0; x < stamp_width; ++x) { + for (unsigned int y = 0; y < stamp_width; ++y) { + for (unsigned int x = 0; x < stamp_width; ++x) { float sum = 0.0; float scale = 0.0; - for (int i = 0; i < num_images; ++i) { + for (unsigned int i = 0; i < num_images; ++i) { float sci_val = sci_stamps[i].get_pixel({y, x}); float var_val = var_stamps[i].get_pixel({y, x}); if (pixel_value_valid(sci_val) && pixel_value_valid(var_val) && (var_val != 0.0)) { diff --git a/src/kbmod/standardizers/fits_standardizers/fits_standardizer.py b/src/kbmod/standardizers/fits_standardizers/fits_standardizer.py index dfce61adc..ae29b21d4 100644 --- a/src/kbmod/standardizers/fits_standardizers/fits_standardizer.py +++ b/src/kbmod/standardizers/fits_standardizers/fits_standardizer.py @@ -410,6 +410,10 @@ def toLayeredImage(self): # copy. TODO: fix when/if CPP stuff is fixed. imgs = [] for sci, var, mask, psf, t in zip(sciences, variances, masks, psfs, mjds): + # Make sure the science and variance layers are float32. + sci = sci.astype(np.float32) + var = var.astype(np.float32) + # Converts nd array mask from bool to np.float32 mask = mask.astype(np.float32) imgs.append(LayeredImage(RawImage(sci, t), RawImage(var, t), RawImage(mask, t), psf))