SourceXtractorPlusPlus 0.18
SourceXtractor++, the next generation SExtractor
MeasurementImageConfig.cpp
Go to the documentation of this file.
1
17/*
18 * @file MeasurementImageConfig.cpp
19 * @author Nikolaos Apostolakos <nikoapos@gmail.com>
20 */
21
22#include <utility>
23#include <limits>
24
25#include <boost/algorithm/string.hpp>
26#include <boost/python/extract.hpp>
27#include <boost/tokenizer.hpp>
28
30
31#include <Pyston/GIL.h>
32
36
42
44
45using namespace Euclid::Configuration;
46namespace fs = boost::filesystem;
47namespace py = boost::python;
48
49namespace SourceXtractor {
50
52 declareDependency<PythonConfig>();
53 declareDependency<WeightImageConfig>();
54 declareDependency<DetectionImageConfig>();
55}
56
57namespace {
58
60
68};
69
70void validateImagePaths(const PyMeasurementImage& image) {
71 if (!fs::exists(image.file)) {
72 throw Elements::Exception() << "File " << image.file << " does not exist";
73 }
74 if (image.weight_file != "" && !fs::exists(image.weight_file)) {
75 throw Elements::Exception() << "File " << image.weight_file << " does not exist";
76 }
77 if (image.psf_file != "" && boost::to_upper_copy(fs::path(image.psf_file).filename().string())!="NOPSF" && !fs::exists(image.psf_file)) {
78 throw Elements::Exception() << "File " << image.psf_file << " does not exist";
79 }
80}
81
82std::shared_ptr<MeasurementImage> createMeasurementImage(
83 std::shared_ptr<FitsImageSource> fits_image_source, double flux_scale) {
85 if (flux_scale != 1.) {
87 }
88 return image;
89}
90
91WeightImageConfig::WeightType getWeightType(const std::string& type_string, const std::string& file_name) {
92 // check for a valid weight type
93 auto weight_type_name = boost::to_upper_copy(type_string);
94 if (weight_type_map.find(weight_type_name) == weight_type_map.end()) {
95 throw Elements::Exception() << "Unknown weight map type for measurement weight image " << file_name << ": "<< type_string;
96 }
97
98 return weight_type_map[weight_type_name];
99}
100
101std::shared_ptr<WeightImage> createWeightMap(const PyMeasurementImage& py_image) {
102 auto weight_type = getWeightType(py_image.weight_type, py_image.weight_file);
103
104 // without an image nothing can be done
105 if (py_image.weight_file == "") {
108 throw Elements::Exception() << "Weight type '" << py_image.weight_type << "' is meaningless without a weight image";
109 }
110
111 return nullptr;
112 }
113
116 throw Elements::Exception() << "Please give an appropriate weight type for image: " << py_image.weight_file;
117 }
118
119 auto weight_image_source =
120 std::make_shared<FitsImageSource>(py_image.weight_file, py_image.weight_hdu+1, ImageTile::FloatImage);
122
123 logger.debug() << "w: " << weight_map->getWidth() << " h: " << weight_map->getHeight()
124 << " t: " << py_image.weight_type << " s: " << py_image.weight_scaling;
125 weight_map = WeightImageConfig::convertWeightMap(weight_map, weight_type, py_image.weight_scaling);
126
127 return weight_map;
128}
129
130WeightImage::PixelType extractWeightThreshold(const PyMeasurementImage& py_image) {
131 if (!py_image.has_weight_threshold) {
133 }
134 WeightImage::PixelType threshold = py_image.weight_threshold;
135 auto weight_type_name = boost::to_upper_copy(py_image.weight_type);
136 switch (weight_type_map[weight_type_name]) {
137 default:
140 threshold = threshold * threshold;
141 break;
143 break;
145 if (threshold > 0) {
146 threshold = 1.0 / threshold;
147 } else {
149 }
150 break;
151 }
152 return threshold;
153}
154
155}
156
158 auto images = getDependency<PythonConfig>().getInterpreter().getMeasurementImages();
159 auto groups = getDependency<PythonConfig>().getInterpreter().getMeasurementGroups();
160
161 // Delegate into Python to log the measurement configuration
162 boost::char_separator<char> line_sep{"\n"};
163 for (auto &g : groups) {
164 Pyston::GILLocker locker;
165 std::string group_str = py::extract<std::string>(g.attr("__str__")());
166 boost::tokenizer<decltype(line_sep)> tok(group_str, line_sep);
167 for (auto &l : tok) {
168 logger.info() << l;
169 }
170 }
171
172 if (images.size() > 0) {
173 for (auto& p : images) {
174 PyMeasurementImage& py_image = p.second;
175 validateImagePaths(py_image);
176
177 logger.debug() << "Loading measurement image: " << py_image.file << " HDU: " << py_image.image_hdu;
178 logger.debug() << "\tWeight: " << py_image.weight_file << " HDU: " << py_image.weight_hdu;
179 logger.debug() << "\tWeight threshold: " << py_image.weight_threshold << " hasThreshold: " << py_image.has_weight_threshold;
180 logger.debug() << "\tPSF: " << py_image.psf_file << " HDU: " << py_image.psf_hdu;
181 logger.debug() << "\tGain: " << py_image.gain;
182 logger.debug() << "\tSaturation: " << py_image.saturation;
183 logger.debug() << "\tFlux scale: " << py_image.flux_scale;
184
185 auto flux_scale = py_image.flux_scale;
186
188
189 info.m_path = py_image.file;
190 info.m_psf_path = py_image.psf_file;
191
192
193 auto fits_image_source =
194 std::make_shared<FitsImageSource>(py_image.file, py_image.image_hdu+1, ImageTile::FloatImage);
195 info.m_measurement_image = createMeasurementImage(fits_image_source, py_image.flux_scale);
196 info.m_coordinate_system = std::make_shared<WCS>(*fits_image_source);
197
198 info.m_gain = py_image.gain / flux_scale;
199 info.m_saturation_level = py_image.saturation * flux_scale;
200 info.m_id = py_image.id;
201
202 info.m_absolute_weight= py_image.weight_absolute;
203 info.m_weight_threshold = extractWeightThreshold(py_image);
204
207
208 auto weight_map = createWeightMap(py_image);
209
210 if (weight_map != nullptr && flux_scale != 1. && py_image.weight_absolute) {
212 weight_map, py_image.flux_scale * py_image.flux_scale);
213 } else {
214 info.m_weight_image = weight_map;
215 }
216
217 info.m_weight_type = getWeightType(py_image.weight_type, py_image.weight_file);
218
219 info.m_image_hdu = py_image.image_hdu + 1;
220 info.m_psf_hdu = py_image.psf_hdu + 1;
221 info.m_weight_hdu = py_image.weight_hdu + 1;
222
223 m_image_infos.emplace_back(std::move(info));
224 }
225 } else {
226 logger.debug() << "No measurement image provided, using the detection image for measurements";
227
228 auto detection_image = getDependency<DetectionImageConfig>();
229 auto weight_image = getDependency<WeightImageConfig>();
230
231 // note: flux scale was already applied
232
234 detection_image.getDetectionImagePath(),
235 "", // psf path
236
237 detection_image.getDetectionImage(),
238 detection_image.getCoordinateSystem(),
239 weight_image.getWeightImage(),
240 weight_image.getWeightType(),
241
242 weight_image.isWeightAbsolute(),
243 weight_image.getWeightThreshold(),
244 (SeFloat) detection_image.getGain(),
245 (SeFloat) detection_image.getSaturation(),
246
247 false,
248 0.0,
249
250 0, // id
251
252 1,1,1 // HDUs
253 });
254
255
256 }
257}
258
259} // end of namespace SourceXtractor
static Logging getLogger(const std::string &name="")
static std::shared_ptr< BufferedImage< T > > create(std::shared_ptr< const ImageSource > source, std::shared_ptr< TileManager > tile_manager=TileManager::getInstance())
std::vector< MeasurementImageInfo > m_image_infos
void initialize(const UserValues &args) override
static std::shared_ptr< ProcessedImage< T, P > > create(std::shared_ptr< const Image< T > > image_a, std::shared_ptr< const Image< T > > image_b)
const int id
Definition: PyId.h:35
static std::shared_ptr< WeightImage > convertWeightMap(std::shared_ptr< WeightImage > weight_image, WeightType weight_type, WeightImage::PixelType scaling=1)
T max(T... args)
T move(T... args)
constexpr double g
SeFloat32 SeFloat
Definition: Types.h:32
static auto logger
Definition: WCS.cpp:44