Alexandria 2.32.0
SDC-CH common library for the Euclid project
Loading...
Searching...
No Matches
PhotometricBandMappingConfig.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2012-2022 Euclid Science Ground Segment
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
24
25#include <algorithm>
26#include <fstream>
27#include <boost/algorithm/string.hpp>
28#include <boost/regex.hpp>
29#include <sstream>
30#include <tuple>
31
33#include "ElementsKernel/Exception.h"
34#include "ElementsKernel/Logging.h"
35
36namespace po = boost::program_options;
37namespace fs = boost::filesystem;
38
39namespace Euclid {
40namespace Configuration {
41
42static Elements::Logging logger = Elements::Logging::getLogger("PhotometricBandMappingConfig");
43
44static const std::string FILTER_MAPPING_FILE{"filter-mapping-file"};
45static const std::string EXCLUDE_FILTER{"exclude-filter"};
46
48
50 return {
51 {"Input catalog options",
52 {{FILTER_MAPPING_FILE.c_str(), po::value<std::string>()->default_value("filter_mapping.txt"),
53 "The file containing the photometry mapping of the catalog columns"},
54 {EXCLUDE_FILTER.c_str(), po::value<std::vector<std::string>>()->default_value(std::vector<std::string>{}, ""),
55 "A list of filters to ignore"}}}};
56}
57
58static fs::path getMappingFileFromOptions(const Configuration::UserValues& args, const fs::path& base_dir) {
59 fs::path mapping_file{args.at(FILTER_MAPPING_FILE).as<std::string>()};
60 if (mapping_file.is_relative()) {
61 mapping_file = base_dir / mapping_file;
62 }
63 if (!fs::exists(mapping_file)) {
64 throw Elements::Exception() << "Photometry mapping file " << mapping_file << " does not exist";
65 }
66 if (fs::is_directory(mapping_file)) {
67 throw Elements::Exception() << "Photometry mapping file " << mapping_file << " is not a file";
68 }
69 return mapping_file;
70}
71
74parseFile(fs::path filename) {
75 PhotometricBandMappingConfig::MappingMap filter_name_mapping{};
77 PhotometricBandMappingConfig::ConvertFromMagMap convert_from_mag_mapping{};
78 std::ifstream in{filename.string()};
79 std::string line;
80
81 bool header_found = false;
82 int filtr_column_index = 0;
83 int flux_column_index = 1;
84 int error_column_index = 2;
85 int upper_limit_column_index = 3;
86 int convertion_column_index = 4;
87
88 std::vector<std::string> expected_column_name{"Filter", "Flux Column", "Error Column", "Upper Limit/error ratio",
89 "Convert from MAG"};
90
91 while (std::getline(in, line)) {
92 line = boost::regex_replace(line, boost::regex("[' ']{2,}"), " ");
93 boost::trim(line);
94 if (line[0] == '#') {
95 if (!header_found) {
96 std::string trimmed_line = line.substr(1);
97 boost::trim(trimmed_line);
98 std::vector<int> proposed_column_index{-1, -1, -1, -1, -1};
100 boost::split(strs, trimmed_line, boost::is_any_of(","));
101
102 for (size_t index = 0; index < expected_column_name.size(); ++index) {
103 for (size_t index_string = 0; index_string < strs.size(); ++index_string) {
104 std::string item = strs[index_string];
105 boost::trim(item);
106 if (item == expected_column_name[index]) {
107 proposed_column_index[index] = index_string;
108 }
109 }
110 }
111
112 if (proposed_column_index[0] >= 0 && proposed_column_index[1] >= 0 && proposed_column_index[2] >= 0) {
113 header_found = true;
114 filtr_column_index = proposed_column_index[0];
115 flux_column_index = proposed_column_index[1];
116 error_column_index = proposed_column_index[2];
117 upper_limit_column_index = proposed_column_index[3];
118 convertion_column_index = proposed_column_index[4];
119 }
120 }
121 continue;
122 }
123
125 boost::split(cells, line, boost::is_any_of(" "));
126
127 try {
128 if (int(cells.size()) <= filtr_column_index || int(cells.size()) <= flux_column_index ||
129 int(cells.size()) <= error_column_index) {
130 throw Elements::Exception() << "File with missing values for the mandatory fields";
131 }
132 std::string filter_value = cells[filtr_column_index];
133 boost::trim(filter_value);
134 std::string flux_value = cells[flux_column_index];
135 boost::trim(flux_value);
136 std::string error_value = cells[error_column_index];
137 boost::trim(error_value);
138
139 filter_name_mapping.emplace_back(filter_value, std::make_pair(flux_value, error_value));
140
141 if (upper_limit_column_index > 0 && int(cells.size()) > upper_limit_column_index &&
142 cells[upper_limit_column_index] != "") {
143 float n = std::stof(cells[upper_limit_column_index]);
144 threshold_mapping.emplace_back(filter_value, n);
145 } else {
146 threshold_mapping.emplace_back(filter_value, 3.0);
147 }
148
149 if (convertion_column_index > 0 && int(cells.size()) > convertion_column_index &&
150 cells[convertion_column_index] != "") {
151 bool f = std::stoi(cells[convertion_column_index]);
152 convert_from_mag_mapping.emplace_back(filter_value, f);
153 } else {
154 convert_from_mag_mapping.emplace_back(filter_value, false);
155 }
156 } catch (const std::exception& e) {
157 logger.error() << "Syntax error in " << filename << ": " << line << " => " << e.what();
158 ;
159 throw Elements::Exception() << "Syntax error in " << filename << ": " << line << " => " << e.what();
160 }
161 }
162 return std::make_tuple(filter_name_mapping, threshold_mapping, convert_from_mag_mapping);
163}
164
166
167 // Parse the file with the mapping
169 auto parsed = parseFile(m_mapping_file);
170 auto all_filter_name_mapping = std::get<0>(parsed);
171 auto all_threshold_mapping = std::get<1>(parsed);
172 auto all_convert_mapping = std::get<2>(parsed);
173
174 // Remove the filters which are marked to exclude
175 auto exclude_vector = args.at(EXCLUDE_FILTER).as<std::vector<std::string>>();
176 std::set<std::string> exclude_filters{exclude_vector.begin(), exclude_vector.end()};
177
178 for (auto& pair : all_threshold_mapping) {
179 if (exclude_filters.count(pair.first) == 0) {
180 m_threshold_map.push_back(pair);
181 }
182 }
183
184 for (auto& pair : all_convert_mapping) {
185 if (exclude_filters.count(pair.first) == 0) {
186 m_convert_from_mag_map.push_back(pair);
187 }
188 }
189
190 for (auto& pair : all_filter_name_mapping) {
191 if (exclude_filters.count(pair.first) > 0) {
192 exclude_filters.erase(pair.first);
193 } else {
194 m_mapping_map.push_back(pair);
195 }
196 }
197
198 if (!exclude_filters.empty()) {
199 std::stringstream wrong_filters{};
200 for (auto& f : exclude_filters) {
201 wrong_filters << f << " ";
202 }
203 throw Elements::Exception() << "Wrong " << EXCLUDE_FILTER << " option value(s) : " << wrong_filters.str();
204 }
205}
206
207void PhotometricBandMappingConfig::setBaseDir(const boost::filesystem::path& base_dir) {
209 throw Elements::Exception() << "setBaseDir() call to initialized PhotometricBandMappingConfig";
210 }
211 m_base_dir = base_dir;
212}
213
216 throw Elements::Exception() << "getPhotometricBandMapping() call to uninitialized "
217 << "PhotometricBandMappingConfig";
218 }
219 return m_mapping_map;
220}
221
225 throw Elements::Exception() << "getUpperLimitThresholdMapping() call to uninitialized "
226 << "PhotometricBandMappingConfig";
227 }
228 return m_threshold_map;
229}
230
233 throw Elements::Exception() << "getConvertFromMagMapping() call to uninitialized "
234 << "PhotometricBandMappingConfig";
235 }
237}
238
241 throw Elements::Exception() << "getMappingFile() call to uninitialized "
242 << "PhotometricBandMappingConfig";
243 }
244 return m_mapping_file;
245}
246
247} // namespace Configuration
248} // namespace Euclid
T at(T... args)
static Logging getLogger(const std::string &name="")
Configuration(long manager_id)
Constructs a new Configuration instance.
State & getCurrentState()
Returns the current state of the configuration.
std::map< std::string, boost::program_options::variable_value > UserValues
@ INITIALIZED
The initialize() method has been called.
std::vector< std::pair< std::string, std::pair< std::string, std::string > > > MappingMap
const boost::filesystem::path getMappingFile()
Returns the mapping file to be used by other configuration class.
std::vector< std::pair< std::string, bool > > ConvertFromMagMap
const MappingMap & getPhotometricBandMapping()
Returns the list of the photometric band mapping which will be red from the catalog.
std::map< std::string, OptionDescriptionList > getProgramOptions() override
Returns the program options defined by the PhotometryCatalogConfig.
const UpperLimitThresholdMap & getUpperLimitThresholdMapping()
Returns the mapping of threshold used in the upper limit computation which will be red from the catal...
PhotometricBandMappingConfig(long manager_id)
Constructs a new PhotometricBandMappingConfig object.
std::vector< std::pair< std::string, float > > UpperLimitThresholdMap
void initialize(const UserValues &args) override
It initializes the photometric bands list.
void setBaseDir(const boost::filesystem::path &base_dir)
Sets the directory used when resolving relative paths.
const ConvertFromMagMap & getConvertFromMagMapping()
Returns the mapping of the flag indicating if the photometry has to be computed from a MAG_AB.
T emplace_back(T... args)
T empty(T... args)
T erase(T... args)
T getline(T... args)
T make_pair(T... args)
T make_tuple(T... args)
static Elements::Logging logger
static const std::string EXCLUDE_FILTER
static std::tuple< PhotometricBandMappingConfig::MappingMap, PhotometricBandMappingConfig::UpperLimitThresholdMap, PhotometricBandMappingConfig::ConvertFromMagMap > parseFile(fs::path filename)
static fs::path getMappingFileFromOptions(const Configuration::UserValues &args, const fs::path &base_dir)
static const std::string FILTER_MAPPING_FILE
T size(T... args)
T stof(T... args)
T stoi(T... args)
T str(T... args)
T substr(T... args)