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