cphot 0.1
A C++ tool for computing photometry from spectra.
library.hpp
Go to the documentation of this file.
1 /**
2  * @defgroup LIBRARY Library of filters
3  * @brief Storage of filters.
4  *
5  * Currently we implement only the HDF5 library format.
6  * This is the format used by <a link=https://github.com/mfouesneau/pyphot> pyphot </a>
7  * and thus one can use its file directly.
8  * (https://github.com/mfouesneau/pyphot)
9  *
10  */
11 #pragma once
12 #include <H5Cpp.h>
13 #include <cphot/filter.hpp>
14 #include <cphot/rquantities.hpp>
15 #include <highfive/H5Easy.hpp>
16 #include <highfive/H5File.hpp>
17 #include <prettyprint.hpp>
18 #include <xtensor/xadapt.hpp>
19 #include <xtensor/xarray.hpp>
20 #include <helpers.hpp>
21 
22 namespace cphot {
23 
24  using DMatrix = xt::xarray<double, xt::layout_type::row_major>;
25 
26  /**
27  * @brief Get a string attribute from a dataset
28  *
29  * @param ds dataset object
30  * @param attribute_name attribute name
31  * @return std::string content of the attribute
32  */
33  std::string get_str_attribute(const H5::DataSet& ds,
34  const std::string & attribute_name){
35 
36  if (!ds.attrExists("DETECTOR"))
37  throw std::runtime_error("Attribute " + attribute_name + " does not exist");
38 
39  std::string attr_str;
40  H5::Attribute attr = ds.openAttribute(attribute_name);
41  H5::StrType stype = attr.getStrType();
42  attr.read(stype, attr_str);
43  return attr_str;
44  }
45 
46  /**
47  * @brief Get a string attribute from a dataset
48  *
49  * @param filename file name
50  * @param path path to the dataset
51  * @param attribute_name attribute name
52  * @return std::string content of the attribute
53  */
54  std::string get_str_attribute(const std::string & filename,
55  const std::string & path,
56  const std::string & attribute_name){
57  H5::H5File file(filename, H5F_ACC_RDONLY);
58  H5::DataSet ds = file.openDataSet(path);
59  return get_str_attribute(ds, attribute_name);
60  }
61 
62  /**
63  * @brief Structure of the HDF5 filter record
64  *
65  * definition of records in HDF5 library datasets (wavelength, transmission)
66  * This structure is needed to read-in the dataset as a compound data type
67  *
68  * this needs HIGHFIVE_REGISTER_TYPE(filter_t, create_compound_filter_t);
69  */
70  typedef struct {
71  double wavelength;
72  double transmission;
73  } filter_t;
74 
75  /**
76  * @brief Create a compound filter t object
77  * @return HighFive::CompoundType
78  *
79  * this needs HIGHFIVE_REGISTER_TYPE(filter_t, create_compound_filter_t);
80  */
81  HighFive::CompoundType create_compound_filter_t(){
82  return {{"WAVELENGTH", HighFive::AtomicType<double>{} },
83  {"THROUGHPUT", HighFive::AtomicType<double>{}} };
84  }
85 
86  /**
87  * @brief Get the filter from hdf5 library object
88  *
89  * @param library_filename where to find the hdf5 library
90  * @param filter_name filter normalized name (dataset group key)
91  * @return Filter filter object
92  */
93  Filter get_filter_from_hdf5_library(const std::string& library_filename,
94  const std::string& filter_name){
95 
96  std::string dataset_path ("/filters/" + filter_name);
97  H5::H5File file(library_filename, H5F_ACC_RDONLY);
98  H5::DataSet ds = file.openDataSet(dataset_path);
99  std::string name = get_str_attribute(ds, "NAME");
100  std::string detector_type = get_str_attribute(ds, "DETECTOR");
101  std::string wavelength_unit = get_str_attribute(ds, "WAVELENGTH_UNIT");
102  file.close();
103 
104  H5Easy::File hf_file(library_filename, H5Easy::File::ReadOnly);
105  HighFive::DataSet hf_ds = hf_file.getDataSet(dataset_path);
106  std::vector<filter_t> data;
107  hf_ds.read(data);
108 
109  std::vector<double> wavelength;
110  std::vector<double> transmission;
111  for (auto & d : data) {
112  wavelength.push_back(d.wavelength);
113  transmission.push_back(d.transmission);
114  }
115 
116  std::vector<std::size_t> shape = { wavelength.size() };
117  DMatrix xt_wave = xt::adapt(wavelength, shape);
118  DMatrix xt_transmit = xt::adapt(transmission, shape);
119 
120  cphot::Filter tmp(xt_wave, xt_transmit,
122  detector_type,
123  name);
124  return tmp;
125  }
126 
127 
128  /**
129  * @ingroup LIBRARY
130  * @brief Storage of filters in HDF5 format
131  *
132  * This is the format used by <a link=https://github.com/mfouesneau/pyphot> pyphot </a>
133  * and thus one can use its file directly.
134  */
135  class HDF5Library {
136 
137  private:
138  std::string source; ///< source of the library
139  std::vector<std::string> content; ///< content of the library
140 
141  public:
142  HDF5Library(const std::string & filename);
143  std::vector<std::string> get_content();
144  Filter load_filter(const std::string & filter_name);
145  std::vector<std::string> find (const std::string & name,
146  bool case_sensitive=true);
147  std::string get_source();
148 
149 
150  };
151 
152  /**
153  * @brief Construct a new HDF5Library object
154  *
155  * @param filename source filename of the HDF5 library
156  */
157  HDF5Library::HDF5Library(const std::string & filename){
158  this->source = filename;
159 
160  // record content of the file (datasets in /filters/)
161  H5Easy::File hf_file(filename, H5Easy::File::ReadOnly);
162  this->content = hf_file.getGroup("filters").listObjectNames();
163  }
164 
165  /**
166  * @brief return the list of filters in the library
167  *
168  * @return std::vector<std::string>
169  */
170  std::vector<std::string> HDF5Library::get_content(){
171  return this->content;
172  }
173 
174  /**
175  * @brief Load a given filter from the library
176  *
177  * @param filter_name normalized names according to the library
178  * @return Filter object
179  */
180  Filter HDF5Library::load_filter(const std::string& filter_name){
181  return get_filter_from_hdf5_library(this->source, filter_name);
182  }
183 
184  /**
185  * @brief Look for filter names
186  *
187  * @param name name to look for
188  * @param case_sensitive set if the case needs to be respected (default true)
189  * @return std::vector<std::string> list of potential candidates
190  */
191  std::vector<std::string> HDF5Library::find (
192  const std::string & name, bool case_sensitive){
193 
194  std::vector<std::string> result;
195 
196  if (case_sensitive) {
197  for (const auto & lib_name: this->get_content()) {
198  if (lib_name.find(name) != std::string::npos)
199  result.push_back(lib_name);
200  }
201  } else {
202  std::string name_lower = tolower(name);
203  for (const auto & lib_name: this->get_content()) {
204  if (tolower(lib_name).find(name) != std::string::npos)
205  result.push_back(lib_name);
206  }
207  }
208  return result;
209  }
210 
211  /**
212  * @brief Get the source filename of the library
213  *
214  * @return std::string filename
215  */
216  std::string HDF5Library::get_source(){
217  return this->source;
218  }
219 
220  /**
221  * @brief Nice representation of Filter objects
222  *
223  * @param os stream to output the representation
224  * @param F Filter object
225  * @return std::ostream& same as os
226  */
227  std::ostream & operator<<(std::ostream &os,
228  HDF5Library &l){
229  os << "HDF5Library: " << l.get_source() << "\n"
230  << " Contains " << l.get_content().size() << " registered filters."
231  << "\n";
232  return os;
233  }
234 };
235 
filter.hpp
cphot::get_str_attribute
std::string get_str_attribute(const H5::DataSet &ds, const std::string &attribute_name)
Get a string attribute from a dataset.
Definition: library.hpp:33
cphot_sun_theoretical::wavelength
const std::vector< double > wavelength
Definition: sun_data.hpp:15
cphot::HDF5Library::HDF5Library
HDF5Library(const std::string &filename)
Construct a new HDF5Library object.
Definition: library.hpp:157
cphot::HDF5Library::load_filter
Filter load_filter(const std::string &filter_name)
Load a given filter from the library.
Definition: library.hpp:180
cphot::operator<<
std::ostream & operator<<(std::ostream &os, Filter &F)
Nice representation of Filter objects.
Definition: filter.hpp:165
helpers.hpp
Some random tools to ease the project.
rquantities.hpp
cphot::DMatrix
xt::xarray< double, xt::layout_type::row_major > DMatrix
Definition: filter.hpp:32
prettyprint.hpp
cphot::Filter
Unit Aware Filter. input spectra and output values have units to avoid mis-interpretation.
Definition: filter.hpp:43
HIGHFIVE_REGISTER_TYPE
HIGHFIVE_REGISTER_TYPE(cphot::filter_t, cphot::create_compound_filter_t)
cphot::filter_t
Structure of the HDF5 filter record.
Definition: library.hpp:70
cphot
Definition: filter.hpp:30
cphot::create_compound_filter_t
HighFive::CompoundType create_compound_filter_t()
Create a compound filter t object.
Definition: library.hpp:81
tolower
std::string tolower(std::string s)
Returns the lower case of a string.
Definition: helpers.hpp:190
cphot::HDF5Library::find
std::vector< std::string > find(const std::string &name, bool case_sensitive=true)
Look for filter names.
Definition: library.hpp:191
cphot::HDF5Library::get_source
std::string get_source()
Get the source filename of the library.
Definition: library.hpp:216
cphot::filter_t::wavelength
double wavelength
Definition: library.hpp:71
cphot_sun_theoretical::wavelength_unit
const QLength wavelength_unit
Definition: sun_data.hpp:19
cphot::filter_t::transmission
double transmission
Definition: library.hpp:72
cphot::get_filter_from_hdf5_library
Filter get_filter_from_hdf5_library(const std::string &library_filename, const std::string &filter_name)
Get the filter from hdf5 library object.
Definition: library.hpp:93
units::parse_length
QLength parse_length(const std::string &str)
find length units from a string
Definition: rquantities.hpp:629
cphot::HDF5Library::get_content
std::vector< std::string > get_content()
return the list of filters in the library
Definition: library.hpp:170
cphot::HDF5Library
Storage of filters in HDF5 format.
Definition: library.hpp:135