CASM
AClustersApproachtoStatisticalMechanics
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules
DataFormatterTools.hh
Go to the documentation of this file.
1 #ifndef DATAFORMATTERTOOLS_HH
2 #define DATAFORMATTERTOOLS_HH
3 #include <numeric>
4 #include <iterator>
5 #include "casm/external/boost.hh"
9 #include "casm/misc/CASM_TMP.hh"
10 
11 namespace CASM {
12 
13  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
14  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
15 
24  template<typename ValueType, typename ArgType, typename DataObject>
29  class DataFormatterOperator : public BaseDatumFormatter<DataObject> {
30  public:
31 
33  using Evaluator = std::function<ValueType(const std::vector<ArgType> &)>;
34  //validator probably not necessary?
35  //using Validator = std::function<bool(const DataObject &)>;
36 
38  const std::string &_init_name,
39  const std::string &_desc,
40  Evaluator evaluator) :
41  BaseDatumFormatter<DataObject>(_init_name, _desc), m_evaluate(evaluator) {}
42 
43  std::unique_ptr<DataFormatterOperator> clone() const {
44  return std::unique_ptr<DataFormatterOperator>(this->_clone());
45  }
46 
49  }
50 
51  std::string short_header(const DataObject &_template_obj) const override;
52 
53  bool validate(const DataObject &_data_obj) const override {
54  return m_arg_formatter.validate(_data_obj);
55  }
56 
57  bool parse_args(const std::string &_args) override;
58 
59  void inject(const DataObject &_data_obj, DataStream &_stream, Index pass_index) const override {
60  if(!validate(_data_obj)) {
61  _stream << DataStream::failbit << ValueType();
62  }
63  else {
64  _stream << _evaluate(_data_obj);
65  }
66  }
67 
68  void print(const DataObject &_data_obj, std::ostream &_stream, Index pass_index) const override {
69  _stream.flags(std::ios::showpoint | std::ios::fixed | std::ios::right);
70  _stream.precision(8);
71  if(validate(_data_obj))
72  _stream << _evaluate(_data_obj);
73  else
74  _stream << "unknown";
75  }
76 
77  jsonParser &to_json(const DataObject &_data_obj, jsonParser &json)const override {
78  if(validate(_data_obj))
79  json = _evaluate(_data_obj);
80  return json;
81  }
82 
83  protected:
84  ValueType _evaluate(const DataObject &_data_obj) const {
85  VectorDataStream<ArgType> vec_stream;
86  vec_stream << m_arg_formatter(_data_obj);
87  return m_evaluate(vec_stream.vector());
88  }
89  private:
90 
91  DataFormatterOperator *_clone() const override {
92  return new DataFormatterOperator(*this);
93  }
94 
97  };
98 
99 
100 
105  template<typename DataObject>
107  return DataFormatterOperator<double, double, DataObject>("add", "Add two or more numbers",
108  [](const std::vector<double> &vec)->double {
109  return std::accumulate(vec.cbegin(),
110  vec.cend(),
111  0.0);
112  });
113 
114  }
115 
120  template<typename DataObject>
122  return DataFormatterOperator<double, double, DataObject>("sub", "Subtract two numbers",
123  [](const std::vector<double> &vec)->double {
124  if(vec.size() != 2)
125  throw std::runtime_error("Subtraction operator must receive exactly two values!");
126  return vec[0] - vec[1];
127  });
128 
129  }
130 
135  template<typename DataObject>
137  return DataFormatterOperator<double, double, DataObject>("mult", "Multiply two or more numbers",
138  [](const std::vector<double> &vec)->double {
139  return std::accumulate(vec.cbegin(),
140  vec.cend(),
141  1.0,
142  [](double a, double b)->double{
143  return a *b;
144  });
145  });
146 
147  }
148 
153  template<typename DataObject>
155  return DataFormatterOperator<double, double, DataObject>("div", "Divide two numbers",
156  [](const std::vector<double> &vec)->double {
157  if(vec.size() != 2)
158  throw std::runtime_error("Division operator must receive exactly two values!");
159  return vec[0] / vec[1];
160  });
161 
162  }
163 
168  template<typename DataObject>
170  return DataFormatterOperator<double, double, DataObject>("max", "Max value of two or more numbers",
171  [](const std::vector<double> &vec)->double {
172  return (*std::max_element(vec.cbegin(),
173  vec.cend()));
174  });
175  }
176 
181  template<typename DataObject>
183  return DataFormatterOperator<double, double, DataObject>("min", "Min value of two or more numbers",
184  [](const std::vector<double> &vec)->double {
185  return (*std::min_element(vec.cbegin(),
186  vec.cend()));
187  });
188  }
189 
194  template<typename DataObject>
196  return DataFormatterOperator<long, double, DataObject>("imax", "Index (from 0) of max value in array of two or more numbers",
197  [](const std::vector<double> &vec)->long {
198  auto it = std::max_element(vec.cbegin(), vec.cend());
199  return std::distance(vec.cbegin(), it);
200  });
201  }
202 
207  template<typename DataObject>
209  return DataFormatterOperator<long, double, DataObject>("imin", "Index (from 0) of min value in array of two or more numbers",
210  [](const std::vector<double> &vec)->long {
211  auto it = std::min_element(vec.cbegin(), vec.cend());
212  return std::distance(vec.cbegin(), it);
213  });
214  }
215 
220  template<typename DataObject>
222  return DataFormatterOperator<double, double, DataObject>("exp", "Exponential function",
223  [](const std::vector<double> &vec)->double {
224  if(vec.size() != 1)
225  throw std::runtime_error("Exponent operator must receive exactly one value!");
226  return exp(vec[0]);
227  });
228 
229  }
230 
231 
238  template<typename DataObject>
240  return DataFormatterOperator<bool, std::string, DataObject>("re", "Check if string matches regular expression. Ex: re('input_string','regex_pattern')",
241  [](const std::vector<std::string> &vec)->bool {
242  if(vec.size() != 2)
243  throw std::runtime_error("Operator re('input_string','regex_pattern') must receive exactly 2 values!");
244  boost::regex e(boost::trim_copy_if(vec[1], boost::is_any_of(" '")));
245  return boost::regex_match(vec[0], e);
246  });
247  }
248 
255  template<typename DataObject>
257  return DataFormatterOperator<bool, std::string, DataObject>("rs", "Check if string contains regular expression. Ex: rs('input_string','regex_pattern')",
258  [](const std::vector<std::string> &vec)->bool {
259  if(vec.size() != 2)
260  throw std::runtime_error("Operator re('input_string','regex_pattern') must receive exactly 2 values!");
261  boost::regex e(boost::trim_copy_if(vec[1], boost::is_any_of(" '")));
262  return boost::regex_search(vec[0], e);
263  });
264  }
265 
270  template<typename DataObject>
272  return DataFormatterOperator<double, double, DataObject>("sq", "Square of a number",
273  [](const std::vector<double> &vec)->double {
274  if(vec.size() != 1)
275  throw std::runtime_error("Square operator must receive exactly one value!");
276  return vec[0] * vec[0];
277  });
278 
279  }
280 
285  template<typename DataObject>
287  return DataFormatterOperator<double, double, DataObject>("sqrt", "Square root of a number",
288  [](const std::vector<double> &vec)->double {
289  if(vec.size() != 1)
290  throw std::runtime_error("Square-root operator must receive exactly one value!");
291  return sqrt(vec[0]);
292  });
293 
294  }
295 
300  template<typename DataObject>
302  return DataFormatterOperator<double, double, DataObject>("neg", "Negative of a number",
303  [](const std::vector<double> &vec)->double {
304  if(vec.size() != 1)
305  throw std::runtime_error("Negation operator must receive exactly one value!");
306  return -vec[0];
307  });
308 
309  }
310 
315  template<typename DataObject>
317  return DataFormatterOperator<bool, bool, DataObject>("and", "Boolean AND for sequence of boolean values",
318  [](const std::vector<bool> &vec)->bool {
319  return std::accumulate(vec.cbegin(),
320  vec.cend(),
321  true,
322  [](bool a, bool b)->bool{
323  return a && b;
324  });
325  });
326 
327  }
328 
333  template<typename DataObject>
335  return DataFormatterOperator<bool, bool, DataObject>("or", "Boolean OR for sequence of boolean values",
336  [](const std::vector<bool> &vec)->bool {
337  return std::accumulate(vec.cbegin(),
338  vec.cend(),
339  false,
340  [](bool a, bool b)->bool{
341  return a || b;
342  });
343  });
344 
345  }
346 
351  template<typename DataObject>
353  return DataFormatterOperator<bool, bool, DataObject>("xor", "Boolean XOR for for two boolean values",
354  [](const std::vector<bool> &vec)->bool {
355  if(vec.size() != 2)
356  throw std::runtime_error("Boolean XOR operator expects exactly two values!");
357  return (vec[0] && !vec[1]) || (!vec[0] && vec[1]);
358  });
359  }
360 
361  template<typename DataObject>
363  return DataFormatterOperator<bool, bool, DataObject>("not", "Boolean NOT for a single boolean value",
364  [](const std::vector<bool> &vec)->bool {
365  if(vec.size() != 1)
366  throw std::runtime_error("Boolean NOT operator must receive exactly one value!");
367  return !vec[0];
368  });
369 
370  }
371 
376  template<typename DataObject>
378  return DataFormatterOperator<bool, double, DataObject>("eq", "Equality comparison for two values",
379  [](const std::vector<double> &vec)->bool {
380  if(vec.size() != 2)
381  throw std::runtime_error("Equality operator must receive exactly two values!");
382  return almost_equal(vec[0], vec[1]);
383  });
384 
385  }
386 
391  template<typename DataObject>
393  return DataFormatterOperator<bool, double, DataObject>("lt", "Less-than comparison for two values",
394  [](const std::vector<double> &vec)->bool {
395  if(vec.size() != 2)
396  throw std::runtime_error("Less-than operator must receive exactly two values!");
397  return vec[0] < vec[1];
398  });
399 
400  }
401 
406  template<typename DataObject>
408  return DataFormatterOperator<bool, double, DataObject>("le", "Less-than-or-equal comparison for two values",
409  [](const std::vector<double> &vec)->bool {
410  if(vec.size() != 2)
411  throw std::runtime_error("Less-than-or-equal operator must receive exactly two values!");
412  return vec[0] <= vec[1];
413  });
414 
415  }
416 
421  template<typename DataObject>
423  return DataFormatterOperator<bool, double, DataObject>("gt", "Greater-than comparison for two values",
424  [](const std::vector<double> &vec)->bool {
425  if(vec.size() != 2)
426  throw std::runtime_error("Greater-than operator must receive exactly two values!");
427  return vec[0] > vec[1];
428  });
429 
430  }
431 
436  template<typename DataObject>
438  return DataFormatterOperator<bool, double, DataObject>("ge", "Greater-than-or-equal comparison for two values",
439  [](const std::vector<double> &vec)->bool {
440  if(vec.size() != 2)
441  throw std::runtime_error("Greater-than-or-equal operator must receive exactly two values!");
442  return vec[0] >= vec[1];
443  });
444 
445  }
446 
448  template<typename DataObject>
451 
452  dict.insert(
453  format_operator_add<DataObject>(),
454  format_operator_sub<DataObject>(),
455  format_operator_mult<DataObject>(),
456  format_operator_div<DataObject>(),
457  format_operator_exp<DataObject>(),
458  format_operator_sq<DataObject>(),
459  format_operator_sqrt<DataObject>(),
460  format_operator_neg<DataObject>(),
461  format_operator_and<DataObject>(),
462  format_operator_or<DataObject>(),
463  format_operator_not<DataObject>(),
464  format_operator_min<DataObject>(),
465  format_operator_max<DataObject>(),
466  format_operator_imin<DataObject>(),
467  format_operator_imax<DataObject>(),
468  format_operator_eq<DataObject>(),
469  format_operator_lt<DataObject>(),
470  format_operator_le<DataObject>(),
471  format_operator_gt<DataObject>(),
472  format_operator_ge<DataObject>(),
473  format_operator_re<DataObject>(),
474  format_operator_rs<DataObject>()
475  );
476 
477  return dict;
478  }
479 
480 
481  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
482  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
483 
488  template<typename DataObject>
489  class DatumFormatterAlias: public BaseDatumFormatter<DataObject> {
490  public:
492 
493  DatumFormatterAlias(const std::string &_name,
494  const std::string &_command,
496  const std::string &_help = "") :
497  BaseDatumFormatter<DataObject> (_name, _help.empty() ? "User-specified alias for '" + _command + "'" : _help) {
498 
500  if(m_format_tags.size() != 1)
501  throw std::runtime_error("Expression '" + _command + "' is either empty or consists of multiple expressions.\n");
502  m_formatter = _dict.lookup(m_format_tags[0])->clone();
503  }
504 
505  DatumFormatterAlias(const std::string &_name, const BaseDatumFormatter<DataObject> &_rhs, const std::string &_help = "") :
506  BaseDatumFormatter<DataObject> (_name, _help.empty() ? "User-specified alias for '" + _rhs.name() + "'" : _help),
507  m_formatter(_rhs.clone()) {}
508 
511  }
512 
513  std::unique_ptr<DatumFormatterAlias> clone() const {
514  return std::unique_ptr<DatumFormatterAlias>(this->_clone());
515  }
516 
517  void init(const DataObject &_template_obj) const override {
518  m_formatter->init(_template_obj);
519  }
520 
522  bool validate(const DataObject &_data_obj) const override {
523  return m_formatter->validate(_data_obj);
524  }
525 
529  std::vector<std::string> col_header(const DataObject &_template_obj) const override {
530  std::vector<std::string> _col;
531  CountDataStream tcount;
532  m_formatter->inject(_template_obj, tcount);
533  if(tcount.count() == 1) {
534  _col.push_back(name());
535  return _col;
536  }
537 
538  for(Index i = 0; i < tcount.count(); i++) {
539  std::stringstream t_ss;
540  t_ss << name() << '(' << i << ')';
541  _col.push_back(t_ss.str());
542  }
543 
544  return _col;
545  }
546 
551  std::string short_header(const DataObject &_template_obj) const override {
552  return name();
553  }
554 
557  Index num_passes(const DataObject &_data_obj) const override {
558  return m_formatter->num_passes(_data_obj);
559  }
560 
563  void print(const DataObject &_data_obj, std::ostream &_stream, Index pass_index = 0) const override {
564  m_formatter->print(_data_obj, _stream, pass_index);
565  }
566 
569  void inject(const DataObject &_data_obj, DataStream &_stream, Index pass_index = 0) const override {
570  m_formatter->inject(_data_obj, _stream, pass_index);
571  }
572 
573 
580  jsonParser &to_json(const DataObject &_data_obj, jsonParser &json)const override {
581  return m_formatter->to_json(_data_obj, json);
582  }
588  bool parse_args(const std::string &args) override {
589 
590  if(!m_formatter) {
591  throw std::runtime_error("ERROR: DataFormatterAlias has no formatter");
592  }
593  //Parse the arguments of of the command now. Later, we may want to do expression substitution
594  // (e.g., "comp_plus = add(comp(a),$1)" where $1 specifies an argument)
595  if(m_subexprs.size() && !m_formatter->parse_args(m_subexprs[0])) {
596  throw std::runtime_error("Invalid arguments passed to '" + m_format_tags[0] + "'. Cannot accept expression '" + m_subexprs[0] + "'\n");
597  }
598 
599  return args.size() == 0;
600  //return m_formatter->parse_args(args);
601  }
602  private:
603 
606  DatumFormatterAlias *_clone() const override {
607  return new DatumFormatterAlias(*this);
608  }
609 
610  std::vector<std::string> m_format_tags, m_subexprs;
612 
613  };
614 
619  template<typename DataObject>
621  const std::string &_name,
622  const std::string &_command,
624  const std::string &_help = "") {
625  return DatumFormatterAlias<DataObject>(_name, _command, _dict, _help);
626  }
627 
632  template<typename DataObject>
634  const std::string &_name,
635  const BaseDatumFormatter<DataObject> &_inside,
636  const std::string &_help = "") {
637  return DatumFormatterAlias<DataObject>(_name, _inside, _help);
638  }
639 
640  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
641  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
642 
647  template<typename ValueType, typename DataObject>
648  class ConstantValueFormatter: public BaseDatumFormatter<DataObject> {
649  public:
651 
652  ConstantValueFormatter(const std::string &_header, const ValueType &_value, bool _print_json = false) :
653  BaseDatumFormatter<DataObject>(_header, "Constant value that will be printed on each line"), m_value(_value), m_print_json(_print_json) {}
654 
655  std::unique_ptr<ConstantValueFormatter> clone() const {
656  return std::unique_ptr<ConstantValueFormatter>(this->_clone());
657  }
658 
659  void inject(const DataObject &_data_obj, DataStream &_stream, Index pass_index) const override {
660  _stream << m_value;
661  }
662 
663  void print(const DataObject &_data_obj, std::ostream &_stream, Index pass_index) const override {
664  _stream << m_value;
665  }
666 
667  jsonParser &to_json(const DataObject &_data_obj, jsonParser &json)const override {
668  if(m_print_json)
669  json = m_value;
670  return json;
671  }
672 
673  private:
674 
675  ConstantValueFormatter *_clone() const override {
676  return new ConstantValueFormatter(*this);
677  }
678 
679 
680  ValueType m_value;
682  };
683 
684  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
685  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
686 
687 
711  template<typename ValueType, typename DataObject>
713  public BaseDatumFormatter<DataObject> {
714 
715  public:
716 
718  BaseValueFormatter(const std::string &_name, const std::string &_desc) :
719  BaseDatumFormatter<DataObject>(_name, _desc) {}
720 
722  virtual ~BaseValueFormatter() {}
723 
724  std::unique_ptr<BaseValueFormatter> clone() const {
725  return std::unique_ptr<BaseValueFormatter>(this->_clone());
726  }
727 
729  virtual ValueType operator()(const DataObject &obj) const {
730  if(!this->validate(obj)) {
731  throw std::runtime_error(std::string("Invalid DataObject in ") + this->name());
732  }
733  return evaluate(obj);
734  }
735 
736 
737  // --- Derived classes require an evaluate member ----
738 
739  virtual ValueType evaluate(const DataObject &obj) const = 0;
740 
741 
742  // --- These methods specialize virtual BaseDatumFormatter<DataObject> methods ----
743 
747  virtual void inject(const DataObject &_data_obj, DataStream &_stream, Index pass_index = 0) const override {
748  if(!this->validate(_data_obj))
749  _stream << DataStream::failbit << ValueType();
750  else
751  _stream << this->evaluate(_data_obj);
752  }
753 
757  virtual void print(const DataObject &_data_obj, std::ostream &_stream, Index pass_index = 0) const override {
758  _stream.flags(std::ios::showpoint | std::ios::fixed | std::ios::right);
759  _stream.precision(8);
760  if(this->validate(_data_obj))
761  _stream << this->evaluate(_data_obj);
762  else
763  _stream << "unknown";
764  }
765 
769  virtual jsonParser &to_json(const DataObject &_data_obj, jsonParser &json) const override {
770  if(this->validate(_data_obj))
771  json = this->evaluate(_data_obj);
772  return json;
773  }
774 
775  private:
776 
778  virtual BaseValueFormatter *_clone() const override = 0;
779  };
780 
781 
782  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
783  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
784 
785 
791  template<typename ValueType, typename DataObject>
792  class GenericDatumFormatter : public BaseValueFormatter<ValueType, DataObject> {
793 
794  public:
795 
796  using Evaluator = std::function<ValueType(const DataObject &)>;
797  using Validator = std::function<bool(const DataObject &)>;
798 
806  GenericDatumFormatter(const std::string &_init_name,
807  const std::string &_desc,
808  Evaluator _evaluator,
809  Validator _validator = always_true<DataObject>) :
810  BaseValueFormatter<ValueType, DataObject>(_init_name, _desc),
811  m_evaluate(_evaluator),
812  m_validate(_validator) {}
813 
814  // /// \brief Destructor
815  // virtual ~GenericDatumFormatter() {}
816 
817  // --- Required implementations -----------
818 
820  ValueType evaluate(const DataObject &obj) const override {
821  return m_evaluate(obj);
822  }
823 
825  std::unique_ptr<GenericDatumFormatter> clone() const {
826  return std::unique_ptr<GenericDatumFormatter>(this->_clone());
827  }
828 
829 
830  // --- Specialized implementation -----------
831 
834  bool validate(const DataObject &obj) const override {
835  return m_validate(obj);
836  }
837 
838 
839  private:
840 
842  GenericDatumFormatter *_clone() const override {
843  return new GenericDatumFormatter(*this);
844  }
845 
848 
849  };
850 
851  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
852  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
853 
892  template<typename Container, typename DataObject>
894  public BaseValueFormatter<Container, DataObject>,
895  public ContainerTraits<Container> {
896 
897  public:
898 
902 
903 
905  Base1DDatumFormatter(const std::string &_name, const std::string &_desc) :
906  BaseValueFormatter<Container, DataObject>(_name, _desc) {}
907 
910 
912  std::unique_ptr<Base1DDatumFormatter> clone() const {
913  return std::unique_ptr<Base1DDatumFormatter>(this->_clone());
914  }
915 
916 
917  // --- These methods specialize virtual BaseValueFormatter<Container, DataObject> methods ----
918 
919 
921  virtual void init(const DataObject &_template_obj) const override {
922  if(_index_rules().size())
923  return;
924 
925  Index size = ContainerTraits<Container>::size(this->evaluate(_template_obj));
926  for(Index i = 0; i < size; i++) {
927  _add_rule(std::vector<Index>({i}));
928  }
929  }
930 
934  virtual std::vector<std::string> col_header(const DataObject &_template_obj) const override {
935  std::vector<std::string> _col;
936  auto it(_index_rules().cbegin()), end_it(_index_rules().cend());
937  Index s = max(8 - int(this->name().size()), 0);
938  for(; it != end_it; ++it) {
939  std::stringstream t_ss;
940  t_ss << std::string(s, ' ') << this->name() << '(' << (*it)[0] << ')';
941  _col.push_back(t_ss.str());
942  }
943  return _col;
944  }
945 
947  virtual bool parse_args(const std::string &args) override {
949  return true;
950  }
951 
955  virtual void inject(const DataObject &_data_obj, DataStream &_stream, Index pass_index = 0) const override {
956 
957  // add_rules to print all elements if not set yet
958  if(!_index_rules().size()) {
959  init(_data_obj);
960  }
961 
962  Container val = this->evaluate(_data_obj);
963  auto it(_index_rules().cbegin()), end_it(_index_rules().cend());
964  if(!this->validate(_data_obj)) {
965  _stream << DataStream::failbit;
966  for(; it != end_it; ++it) {
967  _stream << ValueType();
968  }
969  }
970  else {
971  for(; it != end_it; ++it) {
972  _stream << Access::at(val, (*it)[0]);
973  }
974  }
975  }
976 
980  virtual void print(const DataObject &_data_obj, std::ostream &_stream, Index pass_index = 0) const override {
981 
982  // add_rules to print all elements if not set yet
983  if(!_index_rules().size()) {
984  init(_data_obj);
985  }
986 
987  _stream.flags(std::ios::showpoint | std::ios::fixed | std::ios::right);
988  _stream.precision(8);
989  bool known = this->validate(_data_obj);
990  Container val;
991  if(known)
992  val = this->evaluate(_data_obj);
993  auto it(_index_rules().cbegin()), end_it(_index_rules().cend());
994  for(; it != end_it; ++it) {
995  if(known)
996  _stream << " " << Access::at(val, (*it)[0]);
997  else
998  _stream << " unknown";
999 
1000  }
1001  }
1002 
1003  protected:
1004 
1008 
1009  private:
1010 
1012  virtual Base1DDatumFormatter *_clone() const override = 0;
1013 
1014  };
1015 
1016 
1022  template<typename Container, typename DataObject>
1023  class Generic1DDatumFormatter : public Base1DDatumFormatter<Container, DataObject> {
1024 
1025  public:
1026 
1027  typedef std::function<Container(const DataObject &)> Evaluator;
1028  typedef std::function<bool (const DataObject &)> Validator;
1029 
1037  Generic1DDatumFormatter(const std::string &_name,
1038  const std::string &_desc,
1039  Evaluator _evaluator,
1040  Validator _validator = always_true<DataObject>) :
1041  Base1DDatumFormatter<DataObject, Container>(_name, _desc),
1042  m_evaluate(_evaluator),
1043  m_validate(_validator) {}
1044 
1045 
1046  // --- Required implementations -----------
1047 
1049  Container evaluate(const DataObject &obj) const override {
1050  return m_evaluate(obj);
1051  }
1052 
1054  std::unique_ptr<Generic1DDatumFormatter> clone() const {
1055  return std::unique_ptr<Generic1DDatumFormatter>(this->_clone());
1056  }
1057 
1058 
1059  // --- Specialized implementation -----------
1060 
1063  bool validate(const DataObject &obj) const override {
1064  return m_validate(obj);
1065  }
1066 
1067  private:
1068 
1071  return new Generic1DDatumFormatter(*this);
1072  }
1073 
1074  Evaluator m_evaluate;
1075  Validator m_validate;
1076  };
1077 
1082  template<typename DataObject>
1084 
1089  template<typename DataObject>
1091 
1096  template<typename DataObject>
1098 
1099 
1104  template<typename DataObject>
1106 
1111  template<typename DataObject>
1113 
1118  template<typename DataObject>
1120 
1121 
1126  template<typename DataObject>
1128 
1133  template<typename DataObject>
1135 
1140  template<typename DataObject>
1142 
1143 
1148  template<typename DataObject>
1150 
1155  template<typename DataObject>
1157 
1162  template<typename DataObject>
1164 
1165 
1170  template<typename DataObject>
1172 
1177  template<typename DataObject>
1179 
1184  template<typename DataObject>
1186 
1187 
1191  template<typename DataObject>
1194 
1195  dict.insert(
1196  make_string_dictionary<DataObject>(),
1197  make_boolean_dictionary<DataObject>(),
1198  make_integer_dictionary<DataObject>(),
1199  make_scalar_dictionary<DataObject>(),
1200  make_vectorxd_dictionary<DataObject>()
1201  );
1202 
1203  return dict;
1204  }
1205 
1206  /*
1207  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1208  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1209 
1210  template<typename Container>
1211  std::vector<Index> container_size_2D(const Container &cont) {
1212  std::vector<Index> tsize(2, 0);
1213  tsize[0] = cont.size();
1214  if(tsize[0] > 0)
1215  tsize[1] = cont[0].size();
1216  return tsize;
1217  }
1218 
1225  template<typename _Container,
1226  typename DataObject,
1227  typename _value_type = typename _Container::value_type,
1228  typename _size_type = typename _Container::value_type,
1229  typename Access = CASM_TMP::BracketAccess<_Container, _value_type, _size_type> >
1230  class Generic2DDatumFormatter : public BaseDatumFormatter<DataObject> {
1231  public:
1232  using BaseDatumFormatter<DataObject>::name;
1233  using BaseDatumFormatter<DataObject>::_add_rule;
1234  using BaseDatumFormatter<DataObject>::_index_rules;
1235  using BaseDatumFormatter<DataObject>::_parse_index_expression;
1236  using Container = _Container;
1237  using Evaluator = std::function<Container(const DataObject &)>;
1238  using Sizer = std::function<std::vector<Index>(const Container &)>;
1239  using Validator = std::function<bool(const DataObject &)>;
1240 
1241  Generic2DDatumFormatter(const std::string &_init_name,
1242  const std::string &_desc,
1243  Evaluator evaluator,
1244  Validator validator = always_true<DataObject>,
1245  Sizer sizer = container_size_2D<_Container>) :
1246  BaseDatumFormatter<DataObject>(_init_name, _desc), m_evaluate(evaluator), m_validate(validator), m_size(sizer) {}
1247 
1248  BaseDatumFormatter<DataObject> *clone() const override {
1249  return new Generic2DDatumFormatter(*this);
1250  }
1251 
1252  void init(const DataObject &_template_obj) const override;
1253 
1254  std::string col_header(const DataObject &_template_obj) const override;
1255  std::string short_header(const DataObject &_template_obj) const override;
1256 
1257  bool validate(const DataObject &_data_obj) const override {
1258  return m_validate(_data_obj);
1259  }
1260 
1261  bool parse_args(const std::string &args) override {
1262  _parse_index_expression(args);
1263  return true;
1264  }
1265 
1266  void inject(const DataObject &_data_obj, DataStream &_stream, Index pass_index) const override {
1267  Container val = m_evaluate(_data_obj);
1268  auto it(_index_rules().cbegin()), end_it(_index_rules().cend());
1269  if(!validate(_data_obj))
1270  _stream << DataStream::failbit;
1271  for(; it != end_it; ++it) {
1272  _stream << Access::at(val, (*it)[0], (*it)[1]);
1273  }
1274  }
1275 
1276  void print(const DataObject &_data_obj, std::ostream &_stream, Index pass_index) const override {
1277  _stream.flags(std::ios::showpoint | std::ios::fixed | std::ios::right);
1278  _stream.precision(8);
1279  bool known = validate(_data_obj);
1280  Container val;
1281  if(known)
1282  val = m_evaluate(_data_obj);
1283  auto it(_index_rules().cbegin()), end_it(_index_rules().cend());
1284  for(; it != end_it; ++it) {
1285  if(known)
1286  _stream << " " << Access::at(val, (*it)[0], (*it)[1]);
1287  else
1288  _stream << " unknown";
1289  }
1290  }
1291 
1292  jsonParser &to_json(const DataObject &_data_obj, jsonParser &json)const override {
1293  if(validate(_data_obj))
1294  json = m_evaluate(_data_obj);
1295  return json;
1296  }
1297 
1298  private:
1299  Evaluator m_evaluate;
1300  Validator m_validate;
1301  Sizer m_size;
1302  };
1303 
1304  */
1305 
1306 }
1307 
1309 #endif
Base1DDatumFormatter(const std::string &_name, const std::string &_desc)
Constructor.
DataFormatterOperator(const std::string &_init_name, const std::string &_desc, Evaluator evaluator)
Specialize container traits Expects:
DataFormatterOperator< double, double, DataObject > format_operator_sqrt()
Makes a DataFormatterOperator that returns the square root of a number.
virtual void inject(const DataObject &_data_obj, DataStream &_stream, Index pass_index=0) const override
Default implementation injects each element, via operator<<.
DataFormatterOperator< bool, std::string, DataObject > format_operator_re()
Makes a DataFormatterOperator that checks if a string matches a regular expression.
virtual std::vector< std::string > col_header(const DataObject &_template_obj) const override
Default col_header uses 'name(index)' for each column.
DataFormatterOperator< bool, double, DataObject > format_operator_ge()
Makes a DataFormatterOperator for greater-than-or-equal comparison of two numbers.
void print(const DataObject &_data_obj, std::ostream &_stream, Index pass_index) const override
DataFormatterDictionary< DataObject > make_attribute_dictionary()
Dictionary of all AttributeFormatter (i.e. BaseValueFormatter)
const std::string & name() const
Returns a name for the formatter, which becomes the tag used for parsing.
ConstantValueFormatter * _clone() const override
Make an exact copy of the formatter (including any initialized members)
std::function< ValueType(const DataObject &)> Evaluator
DatumFormatterAlias< DataObject > datum_formatter_alias(const std::string &_name, const std::string &_command, const DataFormatterDictionary< DataObject > &_dict, const std::string &_help="")
Make a DatumFormatterAlias.
DataFormatterOperator< double, double, DataObject > format_operator_div()
Makes a DataFormatterOperator that divides two numbers.
void print(const DataObject &_data_obj, std::ostream &_stream, Index pass_index=0) const override
virtual void inject(const DataObject &_data_obj, DataStream &_stream, Index pass_index=0) const override
Default implementation injects each element.
std::vector< std::string > m_subexprs
void inject(const DataObject &_data_obj, DataStream &_stream, Index pass_index=0) const override
void inject(const DataObject &_data_obj, DataStream &_stream, Index pass_index) const override
Abstract base class for creating 1D DatumFormatter.
jsonParser & to_json(const DataObject &_data_obj, jsonParser &json) const override
DataFormatterOperator< bool, double, DataObject > format_operator_eq()
Makes a DataFormatterOperator for equality comparison of two numbers.
ValueType _evaluate(const DataObject &_data_obj) const
virtual ~BaseValueFormatter()
Destructor.
std::unique_ptr< GenericDatumFormatter > clone() const
Clone.
std::vector< std::string > m_format_tags
ScalarAttributeDictionary< DataObject > make_scalar_dictionary()
Template to be specialized for constructing dictionaries for particular DataObject.
Container evaluate(const DataObject &obj) const override
Returns Container type piece of data about a DataObject, the result of the Evaluator.
DataFormatterOperator< double, double, DataObject > format_operator_exp()
Makes a DataFormatterOperator that returns the exponential of a number.
void split_formatter_expression(const std::string &input_expr, std::vector< std::string > &tag_names, std::vector< std::string > &sub_exprs)
void _add_rule(const std::vector< Index > &new_rule) const
bool validate(const DataObject &obj) const override
Returns boolean indicating if the _evaluator can be used successfully, the result of the Validator...
virtual Base1DDatumFormatter * _clone() const override=0
Clone.
void inject(const DataObject &_data_obj, DataStream &_stream, Index pass_index) const override
DataFormatter< DataObject > m_arg_formatter
ConstantValueFormatter(const std::string &_header, const ValueType &_value, bool _print_json=false)
Main CASM namespace.
Definition: complete.cpp:8
Prints a string value specified at construction. A header string can also be passed.
DataFormatterOperator< bool, double, DataObject > format_operator_le()
Makes a DataFormatterOperator for less-than-or-equal comparison of two numbers.
virtual ValueType evaluate(const DataObject &obj) const =0
BaseDatumFormatter< DataObject >::FormatterType type() const override
Base class for creating scalar DatumFormatter.
ContainerTraits< Container >::Access Access
Access methods for Container.
DataFormatterOperator * _clone() const override
Make an exact copy of the formatter (including any initialized members)
std::unique_ptr< DatumFormatterAlias > clone() const
std::unique_ptr< ConstantValueFormatter > clone() const
int count() const
Definition: DataStream.hh:135
BaseValueFormatter(const std::string &_name, const std::string &_desc)
Constructor.
std::unique_ptr< Base1DDatumFormatter > clone() const
Clone.
DataFormatterOperator< bool, bool, DataObject > format_operator_or()
Makes a DataFormatterOperator that returns the boolean OR for a sequence of boolean values...
void _parse_index_expression(const std::string &_expr)
std::pair< iterator, bool > insert(const value_type &value)
Insert single value.
Definition: unique_map.hh:169
DataFormatterOperator< bool, bool, DataObject > format_operator_and()
Makes a DataFormatterOperator that returns the boolean AND for a sequence of boolean values...
DataFormatterOperator< long, double, DataObject > format_operator_imax()
Makes a DataFormatterOperator that returns the index (from 0) of the maximum of two or more numbers...
bool parse_args(const std::string &_args) override
virtual BaseValueFormatter * _clone() const override=0
Clone.
std::unique_ptr< Generic1DDatumFormatter > clone() const
Clone using copy constructor.
virtual jsonParser & to_json(const DataObject &_data_obj, jsonParser &json) const override
Default implementation calls jsonParser& to_json(const ValueType&, jsonParser&)
bool parse_args(const std::string &args) override
std::function< bool(const DataObject &)> Validator
bool validate(const DataObject &_data_obj) const override
Returns true if _data_obj has valid values for requested data.
DatumFormatterAlias(const std::string &_name, const std::string &_command, const DataFormatterDictionary< DataObject > &_dict, const std::string &_help="")
DataFormatterOperator< double, double, DataObject > format_operator_max()
Makes a DataFormatterOperator that returns the maximum of two or more numbers.
Implements a DatumFormatter that is an alias for a combination of others.
A DatumFormatter that returns a 1D value of specified type, via functions that may be specified at ru...
DataFormatterOperator< bool, bool, DataObject > format_operator_not()
DataFormatterOperator< bool, std::string, DataObject > format_operator_rs()
Makes a DataFormatterOperator that checks if a string contains a regular expression.
GenericDatumFormatter(const std::string &_init_name, const std::string &_desc, Evaluator _evaluator, Validator _validator=always_true< DataObject >)
Constructor.
VectorXdAttributeDictionary< DataObject > make_vectorxd_dictionary()
Template to be specialized for constructing dictionaries for particular DataObject.
virtual ValueType operator()(const DataObject &obj) const
Return requested data from obj, throwing std::runtime_error if not valid.
std::unique_ptr< DataFormatterOperator > clone() const
EigenIndex Index
For long integer indexing:
bool validate(const DataObject &_data_obj) const override
Returns true if _data_obj has valid values for requested data.
std::string short_header(const DataObject &_template_obj) const override
Returns a short expression for the formatter parsing the short_header should allow the formatter to b...
notstd::cloneable_ptr< BaseDatumFormatter< DataObject > > m_formatter
Index num_passes(const DataObject &_data_obj) const override
std::function< ValueType(const std::vector< ArgType > &)> Evaluator
DataFormatterOperator< bool, double, DataObject > format_operator_lt()
Makes a DataFormatterOperator for less-than comparison of two numbers.
std::unique_ptr< BaseValueFormatter > clone() const
DataFormatterOperator< bool, double, DataObject > format_operator_gt()
Makes a DataFormatterOperator for greater-than comparison of two numbers.
jsonParser & to_json(const DataObject &_data_obj, jsonParser &json) const override
DataFormatterOperator< double, double, DataObject > format_operator_add()
Makes a DataFormatterOperator that adds two or more numbers.
GenericDatumFormatter * _clone() const override
Clone.
DatumFormatterAlias(const std::string &_name, const BaseDatumFormatter< DataObject > &_rhs, const std::string &_help="")
T max(const T &A, const T &B)
Definition: CASM_math.hh:32
DataFormatterOperator< bool, bool, DataObject > format_operator_xor()
Makes a DataFormatterOperator that returns the boolean NOT for a single boolean value.
IntegerAttributeDictionary< DataObject > make_integer_dictionary()
Template to be specialized for constructing dictionaries for particular DataObject.
DataFormatterOperator< double, double, DataObject > format_operator_neg()
Makes a DataFormatterOperator that returns the negative of a number.
Generic1DDatumFormatter * _clone() const
Clone using copy constructor.
Abstract base class from which all other DatumFormatter classes inherit.
virtual bool validate(const DataObject &_data_obj) const
Returns true if _data_obj has valid values for requested data.
StringAttributeDictionary< DataObject > make_string_dictionary()
Template to be specialized for constructing dictionaries for particular DataObject.
Generic1DDatumFormatter(const std::string &_name, const std::string &_desc, Evaluator _evaluator, Validator _validator=always_true< DataObject >)
Constructor.
virtual void print(const DataObject &_data_obj, std::ostream &_stream, Index pass_index=0) const override
Default implementation prints each element in a column.
std::string short_header(const DataObject &_template_obj) const override
Returns a short expression for the formatter parsing the short_header should allow the formatter to b...
std::function< bool(const DataObject &)> Validator
bool validate(const DataObject &_obj) const
Returns true if _obj has valid data for all portions of query.
DataFormatterOperator< double, double, DataObject > format_operator_min()
Makes a DataFormatterOperator that returns the minimum of two or more numbers.
BaseDatumFormatter< DataObject >::FormatterType type() const override
const IndexContainer & _index_rules() const
DataFormatterOperator< double, double, DataObject > format_operator_mult()
Makes a DataFormatterOperator that returns the product of two or more numbers.
DataFormatterOperator< long, double, DataObject > format_operator_imin()
Makes a DataFormatterOperator that returns the index (from 0) of the minimum of two or more numbers...
virtual void init(const DataObject &_template_obj) const override
Default initialization adds rules for each element.
std::string _help()
const_iterator lookup(const key_type &_name) const
Equivalent to find, but set 'home' and throws error with suggestion if.
A 'cloneable_ptr' can be used in place of 'unique_ptr'.
DataFormatters that operate on the results of other DataFormatters.
virtual bool parse_args(const std::string &args) override
Default implementation calls _parse_index_expression.
DataFormatterOperator< double, double, DataObject > format_operator_sub()
Makes a DataFormatterOperator that subtracts two numbers.
bool validate(const DataObject &obj) const override
Returns boolean indicating if the _evaluator can be used successfully, the result of the Validator...
A DatumFormatter that returns a value of specified type, via functions that may be specified at runti...
DatumFormatterAlias * _clone() const override
Make an exact copy of the formatter (including any initialized members)
const std::vector< T > & vector() const
Definition: DataStream.hh:336
void print(const DataObject &_data_obj, std::ostream &_stream, Index pass_index) const override
ValueType evaluate(const DataObject &obj) const override
Returns Container type piece of data about a DataObject, the result of the Evaluator.
std::function< Container(const DataObject &)> Evaluator
bool almost_equal(const GenericCluster< CoordType > &LHS, const GenericCluster< CoordType > &RHS, double tol)
virtual void print(const DataObject &_data_obj, std::ostream &_stream, Index pass_index=0) const override
Default implementation prints each element in a column, via operator<<.
void init(const DataObject &_template_obj) const override
A Configuration represents the values of all degrees of freedom in a Supercell.
BooleanAttributeDictionary< DataObject > make_boolean_dictionary()
Template to be specialized for constructing dictionaries for particular DataObject.
DataFormatterDictionary< DataObject > make_operator_dictionary()
Dictionary of all DatumFormatterOperator.
jsonParser & to_json(const DataObject &_data_obj, jsonParser &json) const override
std::vector< std::string > col_header(const DataObject &_template_obj) const override
Returns a std::vector with each column header.
ContainerTraits< Container >::value_type ValueType
virtual ~Base1DDatumFormatter()
Destructor.
DataFormatterOperator< double, double, DataObject > format_operator_sq()
Makes a DataFormatterOperator that returns the square of a number.