SourceXtractorPlusPlus 0.21
SourceXtractor++, the next generation SExtractor
Loading...
Searching...
No Matches
MeasurementImageConfig.cpp
Go to the documentation of this file.
1/*
2 * Copyright © 2019-2022 Université de Genève, LMU Munich - Faculty of Physics, IAP-CNRS/Sorbonne Université
3 *
4 * This library is free software; you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License as published by the Free
6 * Software Foundation; either version 3.0 of the License, or (at your option)
7 * any later version.
8 *
9 * This library is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 * details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18/*
19 * @file MeasurementImageConfig.cpp
20 * @author Nikolaos Apostolakos <nikoapos@gmail.com>
21 */
22
23#include <utility>
24#include <limits>
25
26#include <boost/algorithm/string.hpp>
27#include <boost/python/extract.hpp>
28#include <boost/tokenizer.hpp>
29
30#include <ElementsKernel/Logging.h>
31
32#include <Pyston/GIL.h>
33
37
43
45
46using namespace Euclid::Configuration;
47namespace fs = boost::filesystem;
48namespace py = boost::python;
49
50namespace SourceXtractor {
51
57
58namespace {
59
61
69};
70
71void validateImagePaths(const PyMeasurementImage& image) {
72 if (!fs::exists(image.file)) {
73 throw Elements::Exception() << "File " << image.file << " does not exist";
74 }
75 if (image.weight_file != "" && !fs::exists(image.weight_file)) {
76 throw Elements::Exception() << "File " << image.weight_file << " does not exist";
77 }
78 if (image.psf_file != "" && boost::to_upper_copy(fs::path(image.psf_file).filename().string())!="NOPSF" && !fs::exists(image.psf_file)) {
79 throw Elements::Exception() << "File " << image.psf_file << " does not exist";
80 }
81}
82
83std::shared_ptr<MeasurementImage> createMeasurementImage(
84 std::shared_ptr<FitsImageSource> fits_image_source, double flux_scale) {
86 if (flux_scale != 1.) {
87 image = MultiplyImage<MeasurementImage::PixelType>::create(image, flux_scale);
88 }
89 return image;
90}
91
92WeightImageConfig::WeightType getWeightType(const std::string& type_string, const std::string& file_name) {
93 // check for a valid weight type
94 auto weight_type_name = boost::to_upper_copy(type_string);
95 if (weight_type_map.find(weight_type_name) == weight_type_map.end()) {
96 throw Elements::Exception() << "Unknown weight map type for measurement weight image " << file_name << ": "<< type_string;
97 }
98
99 return weight_type_map[weight_type_name];
100}
101
102std::shared_ptr<WeightImage> createWeightMap(const PyMeasurementImage& py_image) {
103 auto weight_type = getWeightType(py_image.weight_type, py_image.weight_file);
104
105 // without an image nothing can be done
106 if (py_image.weight_file == "") {
109 throw Elements::Exception() << "Weight type '" << py_image.weight_type << "' is meaningless without a weight image";
110 }
111
112 return nullptr;
113 }
114
117 throw Elements::Exception() << "Please give an appropriate weight type for image: " << py_image.weight_file;
118 }
119
120 auto weight_image_source =
121 std::make_shared<FitsImageSource>(py_image.weight_file, py_image.weight_hdu+1, ImageTile::FloatImage);
123 if (py_image.is_data_cube) {
124 weight_image_source->setLayer(py_image.weight_layer);
125 }
126
127 logger.debug() << "w: " << weight_map->getWidth() << " h: " << weight_map->getHeight()
128 << " t: " << py_image.weight_type << " s: " << py_image.weight_scaling;
129 weight_map = WeightImageConfig::convertWeightMap(weight_map, weight_type, py_image.weight_scaling);
130
131 return weight_map;
132}
133
134WeightImage::PixelType extractWeightThreshold(const PyMeasurementImage& py_image) {
135 if (!py_image.has_weight_threshold) {
137 }
138 WeightImage::PixelType threshold = py_image.weight_threshold;
139 auto weight_type_name = boost::to_upper_copy(py_image.weight_type);
140 switch (weight_type_map[weight_type_name]) {
141 default:
144 threshold = threshold * threshold;
145 break;
147 break;
149 if (threshold > 0) {
150 threshold = 1.0 / threshold;
151 } else {
153 }
154 break;
155 }
156 return threshold;
157}
158
159}
160
162 auto images = getDependency<PythonConfig>().getInterpreter().getMeasurementImages();
163
164 if (images.size() > 0) {
165 for (auto& p : images) {
166 PyMeasurementImage& py_image = p.second;
168
169 logger.debug() << "Loading measurement image: " << py_image.file << " HDU: " << py_image.image_hdu;
170 logger.debug() << "\tWeight: " << py_image.weight_file << " HDU: " << py_image.weight_hdu;
171 logger.debug() << "\tWeight threshold: " << py_image.weight_threshold << " hasThreshold: " << py_image.has_weight_threshold;
172 logger.debug() << "\tPSF: " << py_image.psf_file << " HDU: " << py_image.psf_hdu;
173 logger.debug() << "\tGain: " << py_image.gain;
174 logger.debug() << "\tSaturation: " << py_image.saturation;
175 logger.debug() << "\tFlux scale: " << py_image.flux_scale;
176
177 auto flux_scale = py_image.flux_scale;
178
180
181 info.m_path = py_image.file;
182 info.m_psf_path = py_image.psf_file;
183
184 info.m_is_data_cube = py_image.is_data_cube;
185 info.m_image_layer = py_image.image_layer;
186 info.m_weight_layer = py_image.weight_layer;
187
188 auto fits_image_source =
190
191 if (py_image.is_data_cube) {
192 fits_image_source->setLayer(py_image.image_layer);
193 }
194
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;
204
205 info.m_is_background_constant = py_image.is_background_constant;
206 info.m_constant_background_value = py_image.constant_background_value;
207
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 {
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
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
void debug(const std::string &logMessage)
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< WeightImage > convertWeightMap(std::shared_ptr< WeightImage > weight_image, WeightType weight_type, WeightImage::PixelType scaling=1)
T max(T... args)
T move(T... args)
static Elements::Logging logger