CASM
AClustersApproachtoStatisticalMechanics
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules
DataFormatter_impl.hh
Go to the documentation of this file.
5 
6 namespace CASM {
7 
8 
9  //****************************************************************************************
10  template<typename DataObject>
12  //std::cout << "Parsing index expression: " << _expr << "\n";
13  typedef boost::tokenizer<boost::char_separator<char> >
14  tokenizer;
15  boost::char_separator<char> sep1(","), sep2(" \t", ":");
16  tokenizer tok1(_expr, sep1);
17  std::vector<std::string> split_expr(tok1.begin(), tok1.end());
18  std::vector<difference_type> ind_vec_begin(split_expr.size());
19  std::vector<difference_type> ind_vec_end(split_expr.size());
20  for(Index i = 0; i < split_expr.size(); i++) {
21  Index rev_i = split_expr.size() - (i + 1);
22  tokenizer tok2(split_expr[i], sep2);
23  std::vector<std::string> ind_expr(tok2.begin(), tok2.end());
24  if(ind_expr.size() == 1) {
25  if(ind_expr[0][0] == ':')
26  ind_vec_begin[rev_i] = -1;
27  else
28  ind_vec_begin[rev_i] = boost::lexical_cast<difference_type>(ind_expr[0]);
29  ind_vec_end[rev_i] = ind_vec_begin[rev_i];
30  }
31  else if(ind_expr.size() == 3) {
32  ind_vec_begin[rev_i] = boost::lexical_cast<difference_type>(ind_expr[0]);
33  ind_vec_end[rev_i] = boost::lexical_cast<difference_type>(ind_expr[2]);
34  }
35  else
36  throw std::runtime_error(std::string("In BaseDatumFormatter::_parse_index_expression(), invalid expression \"")
37  + _expr + "\" passed as indices for format keyword '" + name() + "'\n");
38  }
39  Counter<std::vector<difference_type> > ind_count(ind_vec_begin, ind_vec_end, std::vector<difference_type>(split_expr.size(), 1));
40  for(; ind_count.valid(); ++ind_count) {
41  m_index_rules.push_back(std::vector<difference_type>(ind_count().rbegin(), ind_count().rend()));
42  }
43 
44  }
45 
46  //******************************************************************************
47 
48  template<typename DataObject>
50  if(!m_initialized)
51  _initialize(_obj);
52  for(Index i = 0; i < m_data_formatters.size(); i++)
53  if(!m_data_formatters[i]->validate(_obj))
54  return false;
55 
56  return true;
57  }
58 
59  //******************************************************************************
60 
61  template<typename DataObject>
62  void DataFormatter<DataObject>::inject(const DataObject &_obj, DataStream &_stream) const {
63  if(!m_initialized)
64  _initialize(_obj);
65 
66  Index num_pass(1), tnum;
67  for(Index i = 0; i < m_data_formatters.size(); i++) {
68  tnum = m_data_formatters[i]->num_passes(_obj);
69  if(tnum == 1)
70  continue;
71  if(num_pass == 1 || tnum == num_pass)
72  num_pass = tnum;
73  else {
74  std::cerr << "CRITICAL ERROR: Requesting to print formatted data elements that require different number of lines.\n"
75  << " Exiting...\n";
76  exit(1);
77  }
78  }
79  for(Index np = 0; np < num_pass; np++) {
80  for(Index i = 0; i < m_data_formatters.size(); i++) {
81  m_data_formatters[i]->inject(_obj, _stream, np);
82  }
83  _stream.newline();
84  }
85 
86  return;
87  }
88 
89  //******************************************************************************
90 
92  template<typename DataObject>
93  template<typename ValueType>
95  ValueDataStream<ValueType> value_stream;
96  value_stream << FormattedObject(this, _obj);
97  return value_stream.value();
98  }
99 
100  //******************************************************************************
101 
103  template<typename DataObject>
104  template<typename ValueType>
105  std::vector<ValueType> DataFormatter<DataObject>::evaluate_as_vector(const DataObject &_obj) const {
106  VectorDataStream<ValueType> value_stream;
107  value_stream << FormattedObject(this, _obj);
108  return value_stream.value();
109  }
110 
111  //******************************************************************************
112 
114  template<typename DataObject>
116  MatrixXdDataStream value_stream;
117  value_stream << FormattedObject(this, _obj);
118  return value_stream.matrix();
119  }
120 
121  //******************************************************************************
122 
124  template<typename DataObject>
125  template<typename ValueType, typename IteratorType>
126  std::vector<ValueType> DataFormatter<DataObject>::evaluate_as_vector(IteratorType begin, IteratorType end) const {
127  VectorDataStream<ValueType> value_stream;
128  value_stream << FormattedObject(this, begin, end);
129  return value_stream.value();
130  }
131 
132  //******************************************************************************
133 
135  template<typename DataObject>
136  template<typename IteratorType>
137  Eigen::MatrixXd DataFormatter<DataObject>::evaluate_as_matrix(IteratorType begin, IteratorType end) const {
138  MatrixXdDataStream value_stream;
139  value_stream << FormattedIteratorPair<IteratorType>(this, begin, end);
140  return value_stream.matrix();
141  }
142 
143  //******************************************************************************
144 
145  template<typename DataObject>
146  void DataFormatter<DataObject>::print(const DataObject &_obj, std::ostream &_stream) const {
147  if(!m_initialized)
148  _initialize(_obj);
149  _stream << std::setprecision(m_prec) << std::fixed;
150  Index num_pass(1), tnum;
151  for(Index i = 0; i < m_data_formatters.size(); i++) {
152  tnum = m_data_formatters[i]->num_passes(_obj);
153  if(tnum == 1)
154  continue;
155  if(num_pass == 1 || tnum == num_pass)
156  num_pass = tnum;
157  else {
158  std::cerr << "CRITICAL ERROR: Requesting to print formatted data elements that require different number of lines.\n"
159  << " Exiting...\n";
160  exit(1);
161  }
162  }
163  std::stringstream t_ss;
164  int depad_request;
165  for(Index np = 0; np < num_pass; np++) {
166  depad_request = 0;
167  for(Index i = 0; i < m_data_formatters.size(); i++) {
168  t_ss.clear();
169  t_ss.str(std::string());
170  m_data_formatters[i]->print(_obj, t_ss, np);
171 
172  // two space fixed separator
173  _stream << " ";
174  //variable separator
175  if(depad_request + 2 < m_col_sep[i])
176  _stream << std::string(m_col_sep[i] - depad_request - 2, ' ');
177  _stream << t_ss.str();
178  depad_request = m_col_sep[i] + int(t_ss.str().size()) - m_col_width[i];
179 
180  }
181  _stream << std::endl;
182  }
183 
184  return;
185  }
186 
187  //******************************************************************************
188 
189  template<typename DataObject>
191  if(!m_initialized)
192  _initialize(_obj);
193  for(Index i = 0; i < m_data_formatters.size(); i++) {
194  m_data_formatters[i]->to_json(_obj, json[m_data_formatters[i]->short_header(_obj)]);
195  }
196 
197  return json;
198  }
199 
200  //******************************************************************************
201 
202  template<typename DataObject>
204  if(!m_initialized) {
205  _initialize(_obj);
206  }
207 
209  jsonParser::iterator end = json.end();
210 
211  for(Index i = 0; i < m_data_formatters.size(); i++) {
212  jsonParser tmp;
213  m_data_formatters[i]->to_json(_obj, tmp);
214  it = json.find(m_data_formatters[i]->short_header(_obj));
215  if(it == end) {
216  json[m_data_formatters[i]->short_header(_obj)].put_array().push_back(tmp);
217  }
218  else {
219  it->push_back(tmp);
220  }
221  }
222 
223  return json;
224  }
225 
226  //******************************************************************************
227 
228  template<typename DataObject>
229  void DataFormatter<DataObject>::print_header(const DataObject &_template_obj, std::ostream &_stream) const {
230  _stream << m_comment;
231  if(!m_initialized)
232  _initialize(_template_obj);
233  int header_size, twidth;
234  for(Index i = 0; i < m_data_formatters.size(); i++) {
235  std::stringstream t_ss;
236  m_data_formatters[i]->print(_template_obj, t_ss);
237  header_size = (m_data_formatters[i]->long_header(_template_obj)).size();
238  twidth = m_sep;
239  if(i == 0)
240  twidth += max(t_ss.str().size(), header_size + m_comment.size());
241  else
242  twidth += max(int(t_ss.str().size()), header_size);
243  m_col_width[i] = twidth;
244  m_col_sep[i] = twidth - int(t_ss.str().size());
245  if(i == 0)
246  twidth -= m_comment.size();
247  _stream << std::string(twidth - header_size, ' ') << m_data_formatters[i]->long_header(_template_obj);
248  }
249  _stream << std::endl;
250  return;
251  }
252 
253  //******************************************************************************
254 
256  template<typename DataObject>
257  std::vector<std::string> DataFormatter<DataObject>::col_header(const DataObject &_template_obj) const {
258  std::vector<std::string> col;
259  for(Index i = 0; i < m_data_formatters.size(); i++) {
260  auto v2 = m_data_formatters[i]->col_header(_template_obj);
261  col.insert(col.end(), v2.begin(), v2.end());
262  }
263  return col;
264  }
265 
266  //******************************************************************************
267 
268  template<typename DataObject>
269  void DataFormatter<DataObject>::_initialize(const DataObject &_template_obj) const {
270  for(Index i = 0; i < m_data_formatters.size(); i++)
271  m_data_formatters[i]->init(_template_obj);
272  m_initialized = true;
273  return;
274  }
275 
276  //******************************************************************************
277 
278 
281  template<typename DataObject, typename DatumFormatterType>
284  const key_type &_name) const {
285 
286  //typedef DataFormatterDictionary<DataObject, DatumFormatterType> dict_type;
287 
288  auto res = this->find(_name);
289  if(res != this->end()) {
290  res->set_home(*this);
291  return res;
292  }
293  else {
294 
295  // If no match, try to use demerescau-levenshtein distance to make a helpful suggestion
296  int min_dist(-1);
297  auto it = this->begin();
298  for(; it != this->end(); ++it) {
299  int dist = dl_string_dist(_name, it->name());
300  if(min_dist < 0 || dist < min_dist) {
301  min_dist = dist;
302  //std::cout << "New best: \"" << it->first << "\" aka \"" << it->second->name() << "\"\n";
303  res = it;
304  }
305  }
306 
307  throw std::runtime_error("CRITICAL ERROR: Invalid format flag \"" + _name + "\" specified.\n"
308  + " Did you mean \"" + res->name() + "\"?\n");
309 
310  }
311 
312  }
313 
317  template<typename DataObject, typename DatumFormatterType>
319  std::ostream &_stream,
321  int width, int separation) const {
322 
323  const_iterator it_begin(this->cbegin()), it_end(this->cend());
324  std::string::size_type len(0);
325  for(auto it = it_begin; it != it_end; ++it) {
326  if(ftype == it->type())
327  len = max(len, it->name().size());
328  }
329  for(auto it = it_begin; it != it_end; ++it) {
330  if(ftype != it->type())
331  continue;
332  _stream << std::string(5, ' ') << it->name() << std::string(len - it->name().size() + separation, ' ');
333  std::string::size_type wcount(0);
334  std::string::const_iterator str_end(it->description().cend());
335  for(std::string::const_iterator str_it = it->description().cbegin(); str_it != str_end; ++str_it) {
336  if(wcount >= width && isspace(*str_it)) {
337  _stream << std::endl << std::string(5 + len + separation, ' ');
338  wcount = 0;
339  }
340  else {
341  _stream << *str_it;
342  wcount++;
343  }
344  }
345  _stream << std::endl << std::endl;
346  }
347  }
348 
349 
357  template<typename DataObject, typename DatumFormatterType>
359  const std::vector<std::string> &input) const {
360 
361  DataFormatter<DataObject> formatter;
362  std::vector<std::string> format_tags, format_args;
363  for(Index i = 0; i < input.size(); i++) {
364  split_formatter_expression(input[i], format_tags, format_args);
365  }
366  for(Index i = 0; i < format_tags.size(); i++) {
367  formatter.push_back(*lookup(format_tags[i]), format_args[i]);
368  }
369  return formatter;
370  }
371 
379  template<typename DataObject, typename DatumFormatterType>
381  const std::string &input) const {
382 
383  DataFormatter<DataObject> formatter;
384  std::vector<std::string> format_tags, format_args;
385  split_formatter_expression(input, format_tags, format_args);
386 
387  for(Index i = 0; i < format_tags.size(); i++) {
388  formatter.push_back(*lookup(format_tags[i]), format_args[i]);
389  }
390  return formatter;
391  }
392 
393 }
Eigen::MatrixXd MatrixXd
std::vector< std::string > col_header(const DataObject &_template_obj) const
Returns all column header strings as std::vector
iterator end()
Returns iterator to end of JSON object or JSON array.
Definition: jsonParser.cc:465
A Counter allows looping over many incrementing variables in one loop.
Definition: Counter.hh:71
jsonParser & to_json(const ClexDescription &desc, jsonParser &json)
An iterator over a UniqueMap.
Definition: unique_map.hh:18
void split_formatter_expression(const std::string &input_expr, std::vector< std::string > &tag_names, std::vector< std::string > &sub_exprs)
Main CASM namespace.
Definition: complete.cpp:8
const Eigen::MatrixXd & matrix()
int dl_string_dist(const std::string &a, const std::string &b)
Computes the Damerescau-Levenshtein distance – the number of edits (deletions, insertions, transpositions) to go from string 'a' to string 'b'.
Definition: CASM_math.cc:42
void _parse_index_expression(const std::string &_expr)
UniqueMapType::key_type key_type
virtual FormatterType type() const
void push_back(const BaseDatumFormatter< DataObject > &new_formatter, const std::string &args)
EigenIndex Index
For long integer indexing:
_DataObject DataObject
Iterator find(Iterator begin, Iterator end, const T &value, BinaryCompare q)
Equivalent to std::find(begin, end, value), but with custom comparison.
Definition: algorithm.hh:10
virtual DataStream & newline()
Definition: DataStream.hh:64
const T & value() const
Definition: DataStream.hh:296
T max(const T &A, const T &B)
Definition: CASM_math.hh:32
Abstract base class from which all other DatumFormatter classes inherit.
iterator find(const std::string &name)
Return iterator to JSON object value with 'name'.
Definition: jsonParser.cc:490
Extract data from objects of 'DataObject' class.
jsonParser & push_back(const T &value)
Puts new valued element at end of array of any type T for which 'jsonParser& to_json( const T &value...
Definition: jsonParser.hh:696
Implements generic formatting member functions for individual data objects.
jsonParser & put_array()
Puts new empty JSON array.
Definition: jsonParser.hh:285
Parsing dictionary for constructing a DataFormatter object.