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