SourceXtractorPlusPlus  0.19
SourceXtractor++, the next generation SExtractor
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
WeightImageConfig.cpp
Go to the documentation of this file.
1 
17 /*
18  * WeightImageConfig.cpp
19  *
20  * Created on: Oct 7, 2016
21  * Author: mschefer
22  */
23 
24 #include <limits>
25 #include <boost/algorithm/string.hpp>
26 #include <boost/regex.hpp>
27 using boost::regex;
28 using boost::regex_match;
29 using boost::smatch;
30 
32 
38 
40 
42 
43 using namespace Euclid::Configuration;
44 namespace po = boost::program_options;
45 
46 namespace SourceXtractor {
47 
48 static const std::string WEIGHT_IMAGE {"weight-image" };
49 static const std::string WEIGHT_TYPE {"weight-type" };
50 static const std::string WEIGHT_ABSOLUTE {"weight-absolute" };
51 static const std::string WEIGHT_SCALING {"weight-scaling" };
52 static const std::string WEIGHT_THRESHOLD {"weight-threshold" };
53 static const std::string WEIGHT_SYMMETRYUSAGE {"weight-use-symmetry" };
54 
55 WeightImageConfig::WeightImageConfig(long manager_id) :
56  Configuration(manager_id),
57  m_weight_type(WeightType::WEIGHT_TYPE_FROM_BACKGROUND),
58  m_absolute_weight(false),
59  m_weight_scaling(1),
60  m_weight_threshold(0),
61  m_symmetry_usage(true) {
62 
63  declareDependency<DetectionImageConfig>();
64 }
65 
67  return { {"Weight image", {
68  {WEIGHT_IMAGE.c_str(), po::value<std::string>()->default_value(""),
69  "Path to a fits format image to be used as weight image."},
70  {WEIGHT_ABSOLUTE.c_str(), po::value<bool>()->default_value(false),
71  "Is the weight map provided as absolute values or relative to background."},
72  {WEIGHT_TYPE.c_str(), po::value<std::string>()->default_value("none"),
73  "Weight image type [none|background|rms|variance|weight]."},
74  {WEIGHT_SCALING.c_str(), po::value<double>()->default_value(1.0),
75  "Weight map scaling factor."},
76  {WEIGHT_THRESHOLD.c_str(), po::value<double>(),
77  "Threshold for pixels to be considered bad pixels. In same units as weight map."},
78  {WEIGHT_SYMMETRYUSAGE.c_str(), po::value<bool>()->default_value(true),
79  "Use object symmetry to replace pixels above the weight threshold for photometry."},
80  }}};
81 }
82 
85 
86  switch (weight_type) {
87  default:
90  return threshold * threshold;
92  return threshold;
94  if (threshold > 0) {
95  return 1.0 / threshold;
96  } else {
98  }
99  }
100 }
101 
102 void WeightImageConfig::initialize(const UserValues& args) {
103  static const std::map<std::string, WeightType> WEIGHT_MAP{
107  {"VARIANCE", WeightType::WEIGHT_TYPE_VARIANCE},
109  };
110 
111  m_absolute_weight = args.find(WEIGHT_ABSOLUTE)->second.as<bool>();
112  m_symmetry_usage = args.find(WEIGHT_SYMMETRYUSAGE)->second.as<bool>();
113 
114  auto weight_image_filename = args.find(WEIGHT_IMAGE)->second.as<std::string>();
115 
116  auto weight_type_name = boost::to_upper_copy(args.at(WEIGHT_TYPE).as<std::string>());
117  auto weight_iter = WEIGHT_MAP.find(weight_type_name);
118  if (weight_iter == WEIGHT_MAP.end()) {
119  throw Elements::Exception() << "Unknown weight map type : " << weight_type_name;
120  }
121  m_weight_type = weight_iter->second;
122  m_weight_scaling = args.find(WEIGHT_SCALING)->second.as<double>();
123 
124  if (args.count(WEIGHT_THRESHOLD) != 0) {
125  auto threshold = args.find(WEIGHT_THRESHOLD)->second.as<double>();
127  } else {
129  }
130 
131  // some safeguards that the user provides reasonable input and gets defined results
132  if (weight_image_filename != "" && m_weight_type == WeightType::WEIGHT_TYPE_FROM_BACKGROUND)
133  throw Elements::Exception() << "Please give an appropriate weight type for image: " << weight_image_filename;
134  if (weight_image_filename != "" && m_weight_type == WeightType::WEIGHT_TYPE_NONE)
135  throw Elements::Exception() << "Please give an appropriate weight type for image: " << weight_image_filename;
136  if (m_absolute_weight && weight_image_filename == "")
137  throw Elements::Exception() << "Setting absolute weight but providing *no* weight image does not make sense.";
138 
139  if (weight_image_filename != "") {
140  boost::regex hdu_regex(".*\\[[0-9]*\\]$");
141 
142  for (int i=0;; i++) {
143  std::shared_ptr<FitsImageSource> fits_image_source;
144  if (boost::regex_match(weight_image_filename, hdu_regex)) {
145  if (i==0) {
146  fits_image_source = std::make_shared<FitsImageSource>(weight_image_filename, 0, ImageTile::FloatImage);
147  } else {
148  break;
149  }
150  } else {
151  try {
152  fits_image_source = std::make_shared<FitsImageSource>(weight_image_filename, i+1, ImageTile::FloatImage);
153  } catch (...) {
154  if (i==0) {
155  // Skip past primary HDU if it doesn't have an image
156  continue;
157  } else {
158  if (m_weight_images.size() == 0) {
159  throw Elements::Exception() << "Can't find 2D image in FITS file: " << weight_image_filename;
160  }
161  break;
162  }
163  }
164  }
165 
167  weight_image = convertWeightMap(weight_image, m_weight_type, m_weight_scaling);
168 
169  // we should have a corresponding detection image
170  auto flux_scale = getDependency<DetectionImageConfig>().getOriginalFluxScale(m_weight_images.size());
171 
172  WeightImage::PixelType scaled_weight_threshold = m_weight_threshold;
173  if (flux_scale != 1. && m_absolute_weight) {
174  weight_image = MultiplyImage<WeightImage::PixelType>::create(weight_image, flux_scale * flux_scale);
175  if (scaled_weight_threshold < std::numeric_limits<WeightImage::PixelType>::max()){
176  // adjust the weight threshold
177  scaled_weight_threshold *= flux_scale * flux_scale;
178  }
179  }
180 
181  m_weight_images.emplace_back(weight_image);
182  m_scaled_weight_thresholds.emplace_back(scaled_weight_threshold);
183  }
184  }
185 }
186 
187 class WeightMapImageSource : public ProcessingImageSource<WeightImage::PixelType> {
188 public:
190  : ProcessingImageSource<DetectionImage::PixelType>(image), m_weight_type(weight_type), m_scaling(scaling)
191  {}
192 
193 protected:
194 
195  std::string getRepr() const override {
196  return "WeightMapImageSource(" + getImageRepr() + ")";
197  }
198 
200  ImageTileWithType<WeightImage::PixelType>& tile, int x, int y, int width, int height) const final {
201  auto image_chunk = image->getChunk(x, y, width, height);
202  switch (m_weight_type) {
204  generateFromRms(tile, width, height, *image_chunk);
205  break;
207  generateFromVariance(tile, width, height, *image_chunk);
208  break;
210  generateFromWeight(tile, width, height, *image_chunk);
211  break;
212  default:
214  assert(false);
215  break;
216  }
217  }
218 
220  const ImageChunk<WeightImage::PixelType>& image_chunk) const {
221  auto& tile_image = *tile.getImage();
222  for (int iy = 0; iy < height; iy++) {
223  for (int ix = 0; ix < width; ix++) {
224  auto value = image_chunk.getValue(ix, iy) * m_scaling;
225  if (value > 0) {
226  tile_image.setValue(ix, iy, 1.0 / value);
227  }
228  else {
229  tile_image.setValue(ix, iy, std::numeric_limits<WeightImage::PixelType>::infinity());
230  }
231  }
232  }
233  }
234 
236  const ImageChunk<WeightImage::PixelType>& image_chunk) const {
237  auto& tile_image = *tile.getImage();
238  for (int iy = 0; iy < height; iy++) {
239  for (int ix = 0; ix < width; ix++) {
240  auto value = image_chunk.getValue(ix, iy) * m_scaling;
241  tile_image.setValue(ix, iy, value);
242  }
243  }
244  }
245 
247  const ImageChunk<WeightImage::PixelType>& image_chunk) const {
248  auto& tile_image = *tile.getImage();
249  for (int iy = 0; iy < height; iy++) {
250  for (int ix = 0; ix < width; ix++) {
251  auto value = image_chunk.getValue(ix, iy) * m_scaling;
252  tile_image.setValue(ix, iy, value * value);
253  }
254  }
255  }
256 
257 private:
260 };
261 
262 
265  WeightImage::PixelType scaling) {
266 
267  if (weight_type == WeightType::WEIGHT_TYPE_FROM_BACKGROUND) {
268  return nullptr;
269  }
270  else if (weight_type == WeightType::WEIGHT_TYPE_NONE) {
271  return nullptr;
272  }
273  else {
275  std::make_shared<WeightMapImageSource>(weight_image, weight_type, scaling));
276  return result_image;
277  }
278 }
279 
280 }
281 
void generateTile(const std::shared_ptr< Image< WeightImage::PixelType >> &image, ImageTileWithType< WeightImage::PixelType > &tile, int x, int y, int width, int height) const final
WeightImage::PixelType m_weight_threshold
WeightMapImageSource(std::shared_ptr< Image< WeightImage::PixelType >> image, WeightImageConfig::WeightType weight_type, WeightImage::PixelType scaling)
void generateFromVariance(ImageTileWithType< WeightImage::PixelType > &tile, int width, int height, const ImageChunk< WeightImage::PixelType > &image_chunk) const
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > x
std::vector< WeightImage::PixelType > m_scaled_weight_thresholds
STL class.
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > y
T getValue(int x, int y) const
Returns the value of the pixel with the coordinates (x,y)
Definition: ImageChunk.h:56
STL class.
static std::shared_ptr< WeightImage > convertWeightMap(std::shared_ptr< WeightImage > weight_image, WeightType weight_type, WeightImage::PixelType scaling=1)
static const std::string WEIGHT_ABSOLUTE
const std::shared_ptr< VectorImage< T > > & getImage() const
Definition: ImageTile.h:178
std::string getRepr() const override
Human readable representation of this source.
WeightImage::PixelType m_weight_scaling
std::map< std::string, Configuration::OptionDescriptionList > getProgramOptions() override
void generateFromWeight(ImageTileWithType< WeightImage::PixelType > &tile, int width, int height, const ImageChunk< WeightImage::PixelType > &image_chunk) const
void initialize(const UserValues &args) override
T c_str(T...args)
Interface representing an image.
Definition: Image.h:43
static WeightImage::PixelType computeWeightThreshold(WeightImageConfig::WeightType weight_type, double threshold)
void generateFromRms(ImageTileWithType< WeightImage::PixelType > &tile, int width, int height, const ImageChunk< WeightImage::PixelType > &image_chunk) const
static const std::string WEIGHT_IMAGE
static const std::string WEIGHT_SCALING
static const std::string WEIGHT_TYPE
WeightImageConfig::WeightType m_weight_type
std::vector< std::shared_ptr< WeightImage > > m_weight_images
static const std::string WEIGHT_THRESHOLD
static std::shared_ptr< ProcessedImage< T, P > > create(std::shared_ptr< const Image< T >> image_a, std::shared_ptr< const Image< T >> image_b)
static std::shared_ptr< BufferedImage< T > > create(std::shared_ptr< const ImageSource > source, std::shared_ptr< TileManager > tile_manager=TileManager::getInstance())
static const std::string WEIGHT_SYMMETRYUSAGE