table_units.h
Go to the documentation of this file.
1 /*
2  -------------------------------------------------------------------
3 
4  Copyright (C) 2006-2020, Andrew W. Steiner
5 
6  This file is part of O2scl.
7 
8  O2scl is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version.
12 
13  O2scl is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with O2scl. If not, see <http://www.gnu.org/licenses/>.
20 
21  -------------------------------------------------------------------
22 */
23 #ifndef O2SCL_TABLE_UNITS_H
24 #define O2SCL_TABLE_UNITS_H
25 
26 /** \file table_units.h
27  \brief File defining \ref o2scl::table_units
28 */
29 
30 #include <o2scl/table.h>
31 #include <o2scl/lib_settings.h>
32 
33 // For the MPI table send and receive functions below
34 #ifdef O2SCL_MPI
35 #include <mpi.h>
36 #endif
37 
38 #ifndef DOXYGEN_NO_O2NS
39 
40 // Forward definition of the table_units class for HDF I/O
41 namespace o2scl {
42  template<class vec_t> class table_units;
43 }
44 
45 // Forward definition of HDF I/O to extend friendship in table_units
46 namespace o2scl_hdf {
47 
48  class hdf_file;
49 
50  template<class vec_t>
51  void hdf_input(hdf_file &hf, o2scl::table_units<vec_t> &t,
52  std::string name);
53 
54  void hdf_output
55  (hdf_file &hf,
56  o2scl::table_units<std::vector<double> > &t,
57  std::string name);
58 
59  template<class vec_t>
60  void hdf_input_data(hdf_file &hf, o2scl::table_units<vec_t> &t);
61 
62  void hdf_output_data
63  (hdf_file &hf,
64  o2scl::table_units<std::vector<double> > &t);
65 
66 }
67 
68 #endif
69 
70 #ifndef DOXYGEN_NO_O2NS
71 namespace o2scl {
72 #endif
73 
74  /** \brief Data \table class with units
75 
76  \future The unit conversion object is now always a pointer to
77  the global conversion object. This could be modified, so that
78  each table can have it's own, but this might require HDF output
79  of unit conversion objects.
80 
81  \future Make table methods virtual? (not necessary yet since
82  delete_column() isn't referred to internally)
83  */
84  template<class vec_t=std::vector<double> >
85  class table_units : public table<vec_t> {
86 
87  public:
88 
89 #ifdef O2SCL_NEVER_DEFINED
90  }{
91 #endif
92 
93  /** \brief Create a new table_units with space for nlines<=cmaxlines.
94  */
95  table_units(int cmaxlines=0) : table<vec_t>(cmaxlines) {
97  }
98 
99  virtual ~table_units() {
100  utree.clear();
101  }
102 
103  /// \name Copy constructors
104  //@{
105  /// Copy with constructor from \ref table_units
106  table_units(const table_units &t) : table<vec_t>(t.get_nlines()) {
107 
108  // Copy constants
109  this->constants=t.constants;
110 
111  // Copy interpolation type
112  this->itype=t.get_interp_type();
113 
114  // Copy the columns and data
115  this->nlines=t.get_nlines();
116  this->maxlines=this->nlines;
117  for(size_t i=0;i<t.get_ncolumns();i++) {
118 
119  // Column name
120  std::string cname=t.get_column_name(i);
121 
122  // Insert column into tree
123  typename table<vec_t>::col s;
124  s.dat.resize(this->nlines);
125  s.index=this->atree.size();
126  this->atree.insert(make_pair(cname,s));
127 
128  // Insert in iterator index
129  typename table<vec_t>::aiter it=this->atree.find(cname);
130  this->alist.push_back(it);
131 
132  // Insert in unit list
133  utree.insert(make_pair(cname,t.get_unit(cname)));
134 
135  // Fill the data
136  for(size_t j=0;j<t.get_nlines();j++) {
137  it->second.dat[j]=t.get(cname,j);
138  }
139 
140  }
141 
142  this->intp_set=false;
144 
145  this->is_valid();
146 
147  return;
148  }
149 
150  /// Copy with constructor from \ref table
151  table_units(const table<vec_t> &t) : table<vec_t>(t.get_nlines()) {
152 
153  // Copy constants
154  this->constants=t.constants;
155 
156  // Copy interpolation type
157  this->itype=t.get_interp_type();
158 
159  // Copy the columns and data
160  this->nlines=t.get_nlines();
161  this->maxlines=this->nlines;
162  for(size_t i=0;i<t.get_ncolumns();i++) {
163 
164  // Column name
165  std::string cname=t.get_column_name(i);
166 
167  // Insert column into tree
168  typename table<vec_t>::col s;
169  s.dat.resize(this->nlines);
170  s.index=this->atree.size();
171  this->atree.insert(make_pair(cname,s));
172 
173  // Insert in iterator index
174  typename table<vec_t>::aiter it=this->atree.find(cname);
175  this->alist.push_back(it);
176 
177  // Fill the data
178  for(size_t j=0;j<t.get_nlines();j++) {
179  it->second.dat[j]=t.get(cname,j);
180  }
181 
182  }
183 
184  this->intp_set=false;
186 
187  this->is_valid();
188 
189  return;
190 
191  }
192 
193  /// Copy with <tt>operator=</tt> from \ref table_units
195 
196  if (this!=&t) {
197 
198  this->clear();
199 
200  // Copy constants
201  this->constants=t.constants;
202 
203  // Copy interpolation type
204  this->itype=t.get_interp_type();
205 
206  // Copy the columns and data
207  this->nlines=t.get_nlines();
208  this->maxlines=this->nlines;
209  for(size_t i=0;i<t.get_ncolumns();i++) {
210 
211  // Column name
212  std::string cname=t.get_column_name(i);
213 
214  // Insert column into tree
215  typename table<vec_t>::col s;
216  s.dat.resize(this->nlines);
217  s.index=this->atree.size();
218  this->atree.insert(make_pair(cname,s));
219 
220  // Insert in iterator index
221  typename table<vec_t>::aiter it=this->atree.find(cname);
222  this->alist.push_back(it);
223 
224  // Insert in unit list
225  utree.insert(make_pair(cname,t.get_unit(cname)));
226 
227  // Fill the data
228  for(size_t j=0;j<t.get_nlines();j++) {
229  it->second.dat[j]=t.get(cname,j);
230  }
231 
232  }
233 
234  if (this->intp_set) {
235  this->intp_set=false;
236  delete this->si;
237  }
238 
240 
241  }
242 
243  this->is_valid();
244 
245  return *this;
246  }
247 
248  /// Copy with <tt>operator=</tt> from \ref table
250 
251  if (this!=&t) {
252 
253  this->clear();
254 
255  // Copy constants
256  this->constants=t.constants;
257 
258  // Copy interpolation type
259  this->itype=t.get_interp_type();
260 
261  // Copy the columns and data
262  this->nlines=t.get_nlines();
263  this->maxlines=this->nlines;
264  for(size_t i=0;i<t.get_ncolumns();i++) {
265 
266  // Column name
267  std::string cname=t.get_column_name(i);
268 
269  // Insert column into tree
270  typename table<vec_t>::col s;
271  s.dat=new vec_t(this->nlines);
272  s.index=this->atree.size();
273  this->atree.insert(make_pair(cname,s));
274 
275  // Insert in iterator index
276  typename table<vec_t>::aiter it=this->atree.find(cname);
277  this->alist.push_back(it);
278 
279  // Fill the data
280  for(size_t j=0;j<t.get_nlines();j++) {
281  (*it->second.dat)[j]=t.get(cname,j);
282  }
283 
284  }
285 
286  if (this->intp_set) {
287  this->intp_set=false;
288  delete this->si;
289  }
290 
292 
293  }
294 
295  this->is_valid();
296 
297  return *this;
298  }
299  //@}
300 
301  /** \brief Copy all rows matching a particular condition to
302  a new table
303 
304  This function begins by ensuring that all columns in the
305  current table are present in \c dest, creating new columns
306  (and copying their units) in \c dest if necessary. It then
307  copies all rows where \c func evaluates to a number greater
308  than 0.5 to table \c dest by adding rows at the end of the
309  table.
310  */
311  template<class vec2_t>
312  void copy_rows(std::string func, table_units<vec2_t> &dest) {
313 
314  // Set up columns
315  for(size_t i=0;i<this->get_ncolumns();i++) {
316  std::string cname=this->get_column_name(i);
317  if (dest.is_column(cname)==false) {
318  dest.new_column(cname);
319  }
320  dest.set_unit(cname,get_unit(cname));
321  }
322 
323  size_t new_lines=dest.get_nlines();
324  for(size_t i=0;i<this->get_nlines();i++) {
325  double val=this->row_function(func,i);
326  if (val>0.5) {
327  this->set_nlines_auto(new_lines+1);
328  for(size_t j=0;j<this->get_ncolumns();j++) {
329  std::string cname=this->get_column_name(j);
330  dest.set(cname,new_lines,this->get(cname,i));
331  }
332  new_lines++;
333  }
334  }
335 
336  return;
337  }
338 
339  /// \name Unit manipulation
340  //@{
341  /// Get the unit for column \c scol
342  std::string get_unit(std::string scol) const {
343 
344  uciter it=utree.find(scol);
345  if (it==utree.end()) {
346  // Not found in unit entry, look for column of data
347  typename table<vec_t>::aciter at=this->atree.find(scol);
348  if (at==this->atree.end()) {
349  O2SCL_ERR((((std::string)"Column '")+scol+
350  "' not found in table_units::get_unit().").c_str(),
351  exc_enotfound);
352  } else {
353  return "";
354  }
355  }
356 
357  return it->second;
358  }
359 
360  /** \brief Specify the units as a string separated by spaces
361  */
362  void line_of_units(std::string unit_line) {
363  std::string unitval;
364 
365  std::istringstream is(unit_line);
366  int icol=0;
367  while(is >> unitval) {
368  if (unitval!=std::string(".")) {
369  this->set_unit(this->get_column_name(icol),unitval);
370  }
371  icol++;
372  }
373  return;
374  }
375 
376  /** \brief Get the unit for column with index i
377 
378  \future Is there a way to make this function have O(1) time
379  rather than searching?
380  */
381  std::string get_unit(size_t i) const {
382  return get_unit(this->get_column_name(i));
383  }
384 
385  /// Remove the unit for column \c scol
386  void remove_unit(std::string scol) {
387 
388  uiter it=utree.find(scol);
389  if (it==utree.end()) {
390  O2SCL_ERR((((std::string)"Column '")+scol+
391  "' not found in table_units::get_unit().").c_str(),
392  exc_enotfound);
393  }
394 
395  if (utree.size()==0) {
396  O2SCL_ERR("No units specified in table_units::remove_unit().",
397  exc_efailed);
398  }
399 
400  utree.erase(it);
401  return;
402  }
403 
404  /// Set the unit for column \c scol to \c unit
405  void set_unit(std::string scol, std::string unit) {
406 
407  uiter it=utree.find(scol);
408  if (it==utree.end()) {
409  typename table<vec_t>::aiter at=this->atree.find(scol);
410  if (at==this->atree.end()) {
411  O2SCL_ERR((((std::string)"Column '")+scol+
412  "' not found in table_units::set_unit().").c_str(),
413  exc_enotfound);
414  }
415  utree.insert(make_pair(scol,unit));
416  } else {
417  it->second=unit;
418  }
419 
420  return;
421  }
422 
423  /// Convert the units of column \c scol to \c unit
424  int convert_to_unit(std::string scol, std::string unit,
425  bool err_on_fail=true) {
426 
427  // Find unit entry
428  uiter it=utree.find(scol);
429  if (it==utree.end()) {
430  if (err_on_fail) {
431  O2SCL_ERR((((std::string)"Column '")+scol+"' not found in "+
432  "table_units::convert_to_unit().").c_str(),
433  exc_enotfound);
434  } else {
435  return exc_enotfound;
436  }
437  };
438 
439  // If the units are equal, just do nothing
440  if (it->second==unit) return success;
441 
442  // Find column of data
443  typename table<vec_t>::aiter at=this->atree.find(scol);
444  if (at==this->atree.end()) {
445  if (err_on_fail) {
446  O2SCL_ERR((((std::string)"Column '")+scol+"' not found in "+
447  "table_units::convert_to_unit().").c_str(),
448  exc_enotfound);
449  } else {
450  return exc_enotfound;
451  }
452  };
453 
454  // Perform conversion
455  vec_t &vec=at->second.dat;
456  double conv=cup->convert(it->second,unit,1.0);
457 
458  for(size_t i=0;i<this->get_nlines();i++) {
459  vec[i]*=conv;
460  }
461 
462  // Set new unit entry
463  it->second=unit;
464 
465  return success;
466  }
467 
468  /// Return the number of columns with units
469  size_t get_nunits() {
470  return utree.size();
471  }
472 
473  /*
474  // Get the conversion factor from \c old_unit to \c new_unit
475  double get_conv(std::string old_unit, std::string new_unit);
476 
477  // Set the convert units object
478  void set_convert(convert_units &c) {
479  cup=&c;
480  return;
481  }
482 
483  // Show the unit cache as given by \ref convert_units::print_cache()
484  void show_units() {
485  cup->print_cache();
486  return;
487  }
488 
489  // The default object for unit conversions
490  convert_units def_cu;
491  */
492  //@}
493 
494  /// \name Virtual functions from \ref table
495  //@{
496 
497  /** \brief Clear the table and the column names and units
498  (but leave constants)
499  */
500  virtual void clear_table() {
501  this->atree.clear();
502  utree.clear();
503  this->alist.clear();
504  this->nlines=0;
505  if (this->intp_set==true) {
506  delete this->si;
507  this->intp_set=false;
508  }
509  return;
510  }
511 
512  /// Delete column named \c scol
513  virtual void delete_column(std::string scol) {
514 
515  // Find the tree iterator for the element we want to erase
516  typename table<vec_t>::aiter it=this->atree.find(scol);
517  if (it==this->atree.end()) {
518  O2SCL_ERR((((std::string)"Column '")+scol+
519  " not found in table_units::delete_column().").c_str(),
520  exc_enotfound);
521  return;
522  }
523 
524  // Remove the unit for the specified column
525  if (get_unit(scol).length()>0) remove_unit(scol);
526 
527  // Find the corresponding list iterator
528  typename table<vec_t>::aviter vit=this->alist.begin();
529  vit+=it->second.index;
530 
531  // Find the last element in the list and it's corresponding table
532  // entry. Change it's index to the index of the column to be
533  // deleted.
534  this->alist[this->alist.size()-1]->second.index=it->second.index;
535 
536  // Erase the elements from the list and the tree
537  this->atree.erase(it);
538  this->alist.erase(vit);
539 
540  // Reset the list to reflect the proper iterators
541  this->reset_list();
542 
543  return;
544  }
545 
546  /** \brief Rename column named \c src to \c dest
547  \f$ {\cal O}(C) \f$
548  */
549  virtual void rename_column(std::string src, std::string dest) {
550  std::string unit=get_unit(src);
551  table<vec_t>::rename_column(src,dest);
552  set_unit(dest,unit);
553  return;
554  }
555 
556  /// Output a summary of the information stored
557  virtual void summary(std::ostream *out, size_t ncol=79) const {
558 
559  if (this->constants.size()==1) {
560  (*out) << "1 constant:" << std::endl;
561  } else {
562  (*out) << this->constants.size() << " constants:" << std::endl;
563  }
564  std::map<std::string,double>::const_iterator mit;
565  for(mit=this->constants.begin();mit!=this->constants.end();mit++) {
566  (*out) << mit->first << " " << mit->second << std::endl;
567  }
568 
569  // Output number of columns and preprend column numbers
570  size_t nh=this->get_ncolumns(), nh2;
571 
572  if (nh==0) {
573 
574  (*out) << "No columns." << std::endl;
575 
576  } else {
577 
578  if (nh==1) {
579  (*out) << "1 column: " << std::endl;
580  } else {
581  (*out) << nh << " columns: " << std::endl;
582  }
583  std::string *h=new std::string[nh];
584  for(size_t i=0;i<nh;i++) {
585  h[i]=szttos(i)+". "+this->get_column_name(i)+" ["+
586  get_unit(this->get_column_name(i))+"]";
587  }
588 
589  std::vector<std::string> h2;
590  // Convert to string with width 'ncol'
591  screenify(nh,h,h2,ncol);
592  nh2=h2.size();
593 
594  // Output column names
595  for(size_t i=0;i<nh2;i++) {
596  (*out) << h2[i] << std::endl;
597  }
598 
599  delete[] h;
600 
601  }
602 
603  if (this->get_nlines()==0) {
604  (*out) << "No lines of data." << std::endl;
605  } else if (this->get_nlines()==1) {
606  (*out) << "One line of data." << std::endl;
607  } else {
608  (*out) << this->get_nlines() << " lines of data." << std::endl;
609  }
610 
611  return;
612  }
613  //@}
614 
615  /// Return the type, \c "table_units".
616  virtual const char *type() { return "table_units"; }
617 
618  /** \brief Copy data from column named \c src to column named \c
619  dest, creating a new column if necessary \f$ {\cal O}(R
620  \log(C)) \f$
621 
622  This function also sets the units of column \c dest to be the
623  same as that in \c src, even if the column named \c dest
624  already exists and previously had different units.
625  */
626  virtual void copy_column(std::string src, std::string dest) {
627  if (!this->is_column(dest)) this->new_column(dest);
628 
629  typedef typename std::map<std::string,
630  typename table<vec_t>::col,std::greater<std::string> >::iterator aiter2;
631 
632  aiter2 its=this->atree.find(src);
633  if (its==this->atree.end()) {
634  O2SCL_ERR((((std::string)"Column '")+src+
635  " not found in table_units::copy_column().").c_str(),
636  exc_enotfound);
637  return;
638  }
639  aiter2 itd=this->atree.find(dest);
640  if (itd==this->atree.end()) {
641  O2SCL_ERR((((std::string)"Destination column '")+dest+
642  " not found in table_units::copy_column().").c_str(),
643  exc_esanity);
644  return;
645  }
646  this->set_unit(dest,this->get_unit(src));
647  for(size_t i=0;i<this->nlines;i++) {
648  itd->second.dat[i]=its->second.dat[i];
649  }
650  return;
651  }
652 
653  /// Clear the current table and read from a generic data file
654  virtual int read_generic(std::istream &fin, int verbose=0) {
655 
656  double data;
657  std::string line;
658  std::string stemp;
659  std::istringstream *is;
660 
661  // Read first line and into list
662  std::vector<std::string> onames, nnames;
663  getline(fin,line);
664  is=new std::istringstream(line);
665  while ((*is) >> stemp) {
666  onames.push_back(stemp);
667  if (verbose>2) {
668  std::cout << "Read possible column name: " << stemp << std::endl;
669  }
670  }
671  delete is;
672 
673  // Count number of likely numbers in the first row
674  size_t n_nums=0;
675  for(size_t i=0;i<onames.size();i++) {
676  if (is_number(onames[i])) n_nums++;
677  }
678 
679  int irow=0;
680 
681  if (n_nums==onames.size()) {
682 
683  if (verbose>0) {
684  std::cout << "First row looks like it contains numerical values."
685  << std::endl;
686  std::cout << "Creating generic column names: ";
687  }
688 
689  for(size_t i=0;i<onames.size();i++) {
690  nnames.push_back(((std::string)"c")+szttos(i+1));
691  if (verbose>0) std::cout << nnames[i] << " ";
692 
693  }
694  if (verbose>0) std::cout << std::endl;
695 
696  // Make columns
697  for(size_t i=0;i<nnames.size();i++) {
698  this->new_column(nnames[i]);
699  }
700 
701  // Add first row of data
702  this->set_nlines_auto(irow+1);
703  for(size_t i=0;i<onames.size();i++) {
704  this->set(i,irow,o2scl::stod(onames[i]));
705  }
706  irow++;
707 
708  } else {
709 
710  // Ensure good column names
711  for(size_t i=0;i<onames.size();i++) {
712  std::string temps=onames[i];
713  this->make_fp_varname(temps);
714  this->make_unique_name(temps,nnames);
715  nnames.push_back(temps);
716  if (temps!=onames[i] && verbose>0) {
717  std::cout << "Converted column named '" << onames[i] << "' to '"
718  << temps << "'." << std::endl;
719  }
720  }
721 
722  // Make columns
723  for(size_t i=0;i<nnames.size();i++) {
724  this->new_column(nnames[i]);
725  }
726 
727  // Read another line, and see if it looks like units
728  std::vector<std::string> units;
729  getline(fin,line);
730  is=new std::istringstream(line);
731  int num_units=0;
732  while ((*is) >> stemp) {
733  units.push_back(stemp);
734  if (stemp[0]=='[') num_units++;
735  if (verbose>2) {
736  std::cout << "Read word in second row: " << stemp << std::endl;
737  }
738  }
739  delete is;
740 
741  if (units.size()!=nnames.size()) {
742  std::cout << "Second row appears not to have same number of "
743  << "entries as the first." << std::endl;
744  std::cout << "Aborting." << std::endl;
745  return -1;
746  }
747 
748  if (num_units==((int)units.size()) || num_units>2) {
749  if (verbose>2) {
750  std::cout << "Looks like second row contains units." << std::endl;
751  }
752  for(size_t i=0;i<units.size();i++) {
753  // Remove brackets
754  stemp=units[i];
755  if (stemp[0]=='[') stemp=stemp.substr(1,stemp.length()-1);
756  if (stemp[stemp.length()-1]==']') {
757  stemp=stemp.substr(0,stemp.length()-1);
758  }
759  // Set the units
760  set_unit(nnames[i],stemp);
761  if (verbose>2) {
762  std::cout << "Name,unit: " << nnames[i] << " [" << stemp << "]"
763  << std::endl;
764  }
765  }
766 
767  } else {
768 
769  // Otherwise, assume this is a row of data
770  this->set_nlines_auto(1);
771  for(size_t i=0;i<units.size();i++) {
772  this->set(i,0,o2scl::stod(units[i]));
773  }
774  irow++;
775 
776  }
777 
778  }
779 
780  // Read remaining rows
781  while ((fin) >> data) {
782  this->set_nlines_auto(irow+1);
783  this->set(0,irow,data);
784  for(size_t i=1;i<this->get_ncolumns();i++) {
785  (fin) >> data;
786  this->set(i,irow,data);
787  }
788  irow++;
789  }
790 
791  return 0;
792  }
793 
794  /** \brief Insert columns from a source table into the new
795  table by interpolation (or extrapolation)
796 
797  This takes all of the columns in \c source, and adds them into
798  the current table using interpolation, using the columns \c
799  src_index and \c dest_index as the independent variable. The
800  column named \c src_index is the column of the independent
801  variable in \c source and the column named \c dest_index
802  is the column of the independent variable in the current table.
803  If \c dest_index is empty (the default) then the names in the
804  two tables are taken to be the same.
805 
806  If necessary, columns are created in the current table for the
807  dependent variable columns in \c source. Columns in the current
808  table which do not correspond to dependent variable columns in
809  \c source are left unchanged.
810 
811  If \c allow_extrap is false, then extrapolation is not allowed,
812  and rows in the current table which have values of the independent
813  variable which are outside the source table are unmodified.
814 
815  If a column for a dependent variable in \c source has the
816  same name as \c dest_index, then it is ignored and not inserted
817  into the current table.
818 
819  If the column named \c src_index cannot be found in
820  \c source or the column names \c dest_index cannot be found
821  in the current table, then the error handler is called.
822 
823  If the \c allow_extrap is false and either the minimum or
824  maximum values of the column named \c src_index in the \c source
825  table are not finite, then the error handler is called.
826  */
827  template<class vec2_t>
828  void insert_table(table_units<vec2_t> &source, std::string src_index,
829  bool allow_extrap=true, std::string dest_index="") {
830 
831  if (dest_index=="") dest_index=src_index;
832 
833  if (!source.is_column(src_index)) {
834  O2SCL_ERR("Source indep. var. column not found.",o2scl::exc_einval);
835  }
836  if (!this->is_column(dest_index)) {
837  O2SCL_ERR("Dest. indep. var. column not found.",o2scl::exc_einval);
838  }
839 
840  // Find limits to avoid extrapolation if necessary
841  double min=source.min(src_index);
842  double max=source.max(src_index);
843  if (allow_extrap==false) {
844  if (!std::isfinite(min) || !std::isfinite(max)) {
845  O2SCL_ERR2("Minimum or maximum of source index not finite ",
846  "in table_units::insert_table().",exc_einval);
847  }
848  }
849 
850  // Create list of columns to interpolate
851  std::vector<std::string> col_list;
852  for(size_t i=0;i<source.get_ncolumns();i++) {
853  std::string col=source.get_column_name(i);
854  if (col!=src_index && col!=dest_index) {
855  col_list.push_back(col);
856  }
857  }
858 
859  // Create new columns and perform interpolation
860  for(size_t i=0;i<col_list.size();i++) {
861  if (!this->is_column(col_list[i])) this->new_column(col_list[i]);
862  set_unit(col_list[i],source.get_unit(col_list[i]));
863  for(size_t j=0;j<this->get_nlines();j++) {
864  double val=this->get(dest_index,j);
865  if (allow_extrap || (val>=min && val<=max)) {
866  this->set(col_list[i],j,source.interp(src_index,val,col_list[i]));
867  }
868  }
869  }
870 
871  return;
872  }
873 
874  // ---------
875  // Allow HDF I/O functions to access table_units data
876  friend void o2scl_hdf::hdf_output
877  (o2scl_hdf::hdf_file &hf, table_units<> &t, std::string name);
878 
879  template<class vecf_t> friend void o2scl_hdf::hdf_input
880  (o2scl_hdf::hdf_file &hf, table_units<vecf_t> &t, std::string name);
881 
882  friend void o2scl_hdf::hdf_output_data
884 
885  template<class vecf_t> friend void o2scl_hdf::hdf_input_data
887 
888  // ---------
889 
890 #ifndef DOXYGEN_INTERNAL
891 
892  protected:
893 
894 
895  /// The pointer to the convert units object
897 
898  /// \name Unit map iterator types
899  //@{
900  typedef std::map<std::string,std::string,
901  std::greater<std::string> >::iterator uiter;
902  typedef std::map<std::string,std::string,
903  std::greater<std::string> >::const_iterator uciter;
904  //@}
905 
906  /// Unit map
907  std::map<std::string,std::string,std::greater<std::string> > utree;
908 
909 #endif
910 
911  };
912 
913 #ifdef O2SCL_MPI
914 
915  /** \brief Send a \ref o2scl::table_units object to
916  MPI rank \c dest_rank
917  */
918  template<class vec_t>
919  void o2scl_table_mpi_send(o2scl::table_units<vec_t> &t, size_t dest_rank) {
920 
921  int tag;
922  int ibuffer;
923  std::vector<double> dbuffer;
924  std::string cbuffer;
925 
926  // --------------------------------------------------------------
927  // Constant names and values
928 
929  for(size_t i=0;i<t.get_nconsts();i++) {
930  std::string name;
931  double val;
932  t.get_constant(i,name,val);
933  cbuffer+=name;
934  if (i<t.get_nconsts()-1) {
935  cbuffer+=' ';
936  }
937  dbuffer.push_back(val);
938  }
939 
940  ibuffer=cbuffer.length();
941 
942  tag=0;
943  MPI_Send(&ibuffer,1,MPI_INT,dest_rank,
944  tag,MPI_COMM_WORLD);
945  tag=1;
946  MPI_Send(&(cbuffer[0]),cbuffer.length(),MPI_CHAR,dest_rank,
947  tag,MPI_COMM_WORLD);
948  tag=2;
949  MPI_Send(&(dbuffer[0]),dbuffer.size(),MPI_DOUBLE,dest_rank,
950  tag,MPI_COMM_WORLD);
951  cbuffer.clear();
952  dbuffer.clear();
953 
954  // --------------------------------------------------------------
955  // Column names
956 
957  for(size_t i=0;i<t.get_ncolumns();i++) {
958  std::string name=t.get_column_name(i);
959  cbuffer+=name;
960  if (i<t.get_ncolumns()-1) {
961  cbuffer+=' ';
962  }
963  }
964 
965  ibuffer=cbuffer.length();
966  tag=3;
967  MPI_Send(&ibuffer,1,MPI_INT,dest_rank,
968  tag,MPI_COMM_WORLD);
969  tag=4;
970  MPI_Send(&(cbuffer[0]),cbuffer.length(),MPI_CHAR,dest_rank,
971  tag,MPI_COMM_WORLD);
972  cbuffer.clear();
973 
974  // --------------------------------------------------------------
975  // Column units
976 
977  for(size_t i=0;i<t.get_ncolumns();i++) {
978  std::string unit=t.get_unit(t.get_column_name(i));
979  cbuffer+=unit;
980  if (i<t.get_ncolumns()-1) {
981  cbuffer+=' ';
982  }
983  }
984 
985  ibuffer=cbuffer.length();
986  tag=5;
987  MPI_Send(&ibuffer,1,MPI_INT,dest_rank,
988  tag,MPI_COMM_WORLD);
989  tag=6;
990  MPI_Send(&(cbuffer[0]),cbuffer.length(),MPI_CHAR,dest_rank,
991  tag,MPI_COMM_WORLD);
992  cbuffer.clear();
993 
994  // --------------------------------------------------------------
995  // Interpolation type
996 
997  tag=7;
998  ibuffer=t.get_interp_type();
999  MPI_Send(&ibuffer,1,MPI_INT,dest_rank,
1000  tag,MPI_COMM_WORLD);
1001 
1002  // --------------------------------------------------------------
1003  // Column data
1004 
1005  ibuffer=t.get_nlines();
1006  tag=8;
1007  MPI_Send(&ibuffer,1,MPI_INT,dest_rank,
1008  tag,MPI_COMM_WORLD);
1009 
1010  for(size_t i=0;i<t.get_ncolumns();i++) {
1011  tag++;
1012  MPI_Send(&(t[i][0]),t.get_nlines(),MPI_DOUBLE,dest_rank,
1013  tag,MPI_COMM_WORLD);
1014  }
1015 
1016  return;
1017  }
1018 
1019  /** \brief Receive a \ref o2scl::table_units object from
1020  MPI rank \c src_rank
1021  */
1022  template<class vec_t>
1023  void o2scl_table_mpi_recv(size_t src_rank,
1025  int tag;
1026  int ibuffer;
1027  // Not std::string because we need to guarantee contiguous storage?!
1028  std::vector<char> cbuffer;
1029  std::vector<double> dbuffer;
1030 
1031  std::vector<std::string> names;
1032  std::string stemp;
1033 
1034  // --------------------------------------------------------------
1035  // Constants
1036 
1037  // Names
1038  tag=0;
1039  MPI_Recv(&ibuffer,1,MPI_INT,src_rank,tag,MPI_COMM_WORLD,
1040  MPI_STATUS_IGNORE);
1041  cbuffer.resize(ibuffer);
1042  tag=1;
1043  MPI_Recv(&(cbuffer[0]),ibuffer,MPI_CHAR,src_rank,tag,MPI_COMM_WORLD,
1044  MPI_STATUS_IGNORE);
1045 
1046  // Parse into std::vector<string>
1047  for(size_t i=0;i<cbuffer.size();i++) {
1048  if (cbuffer[i]!=' ') {
1049  stemp+=cbuffer[i];
1050  } else {
1051  if (stemp.size()>0) {
1052  names.push_back(stemp);
1053  stemp="";
1054  }
1055  }
1056  }
1057  if (stemp.size()>0) {
1058  names.push_back(stemp);
1059  }
1060  stemp="";
1061 
1062  // Load values
1063  dbuffer.resize(names.size());
1064 
1065  tag=2;
1066  MPI_Recv(&(dbuffer[0]),dbuffer.size(),MPI_DOUBLE,
1067  src_rank,tag,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
1068 
1069  // Set constants
1070  for(size_t i=0;i<names.size();i++) {
1071  t.add_constant(names[i],dbuffer[i]);
1072  }
1073  names.clear();
1074  dbuffer.clear();
1075 
1076  // --------------------------------------------------------------
1077  // Column names
1078 
1079  tag=3;
1080  MPI_Recv(&ibuffer,1,MPI_INT,src_rank,tag,MPI_COMM_WORLD,
1081  MPI_STATUS_IGNORE);
1082  cbuffer.resize(ibuffer);
1083  tag=4;
1084  MPI_Recv(&(cbuffer[0]),ibuffer,MPI_CHAR,src_rank,tag,MPI_COMM_WORLD,
1085  MPI_STATUS_IGNORE);
1086 
1087  // Parse into std::vector<string>
1088  for(size_t i=0;i<cbuffer.size();i++) {
1089  if (cbuffer[i]!=' ') {
1090  stemp+=cbuffer[i];
1091  } else {
1092  if (stemp.size()>0) {
1093  names.push_back(stemp);
1094  stemp="";
1095  }
1096  }
1097  }
1098  if (stemp.size()>0) {
1099  names.push_back(stemp);
1100  }
1101  stemp="";
1102 
1103  for(size_t i=0;i<names.size();i++) {
1104  t.new_column(names[i]);
1105  }
1106  names.clear();
1107 
1108  // --------------------------------------------------------------
1109  // Column units
1110 
1111  tag=5;
1112  MPI_Recv(&ibuffer,1,MPI_INT,src_rank,tag,MPI_COMM_WORLD,
1113  MPI_STATUS_IGNORE);
1114  cbuffer.resize(ibuffer);
1115  tag=6;
1116  MPI_Recv(&(cbuffer[0]),ibuffer,MPI_CHAR,src_rank,tag,MPI_COMM_WORLD,
1117  MPI_STATUS_IGNORE);
1118 
1119  // Parse into std::vector<string>
1120  for(size_t i=0;i<cbuffer.size();i++) {
1121  if (cbuffer[i]!=' ') {
1122  stemp+=cbuffer[i];
1123  } else {
1124  if (stemp.size()>0) {
1125  names.push_back(stemp);
1126  stemp="";
1127  }
1128  }
1129  }
1130  if (stemp.size()>0) {
1131  names.push_back(stemp);
1132  }
1133  stemp="";
1134 
1135  for(size_t i=0;i<names.size();i++) {
1136  t.set_unit(t.get_column_name(i),names[i]);
1137  }
1138  names.clear();
1139 
1140  // --------------------------------------------------------------
1141  // Column data
1142 
1143  tag=7;
1144  MPI_Recv(&ibuffer,1,MPI_INT,src_rank,tag,MPI_COMM_WORLD,
1145  MPI_STATUS_IGNORE);
1146  t.set_interp_type(ibuffer);
1147 
1148  // --------------------------------------------------------------
1149  // Column data
1150 
1151  tag=8;
1152  MPI_Recv(&ibuffer,1,MPI_INT,src_rank,tag,MPI_COMM_WORLD,
1153  MPI_STATUS_IGNORE);
1154  t.set_nlines(ibuffer);
1155 
1156  for(size_t i=0;i<t.get_ncolumns();i++) {
1157  tag++;
1158  std::vector<double> v(t.get_maxlines());
1159  MPI_Recv(&(v[0]),ibuffer,MPI_DOUBLE,src_rank,
1160  tag,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
1161  t.swap_column_data(t.get_column_name(i),v);
1162  }
1163 
1164  return;
1165  }
1166 
1167 #endif
1168 
1169 #ifndef DOXYGEN_NO_O2NS
1170 }
1171 #endif
1172 
1173 #endif
o2scl::table_units::get_unit
std::string get_unit(std::string scol) const
Get the unit for column scol.
Definition: table_units.h:342
o2scl::is_number
bool is_number(std::string s)
Return true if the string s is likely a integral or floating point number.
o2scl::table
Data table table class.
Definition: table.h:49
o2scl::table_units::line_of_units
void line_of_units(std::string unit_line)
Specify the units as a string separated by spaces.
Definition: table_units.h:362
o2scl::table::get_nlines
size_t get_nlines() const
Return the number of lines.
Definition: table.h:460
o2scl::table_units::copy_column
virtual void copy_column(std::string src, std::string dest)
Copy data from column named src to column named dest, creating a new column if necessary .
Definition: table_units.h:626
o2scl::table::constants
std::map< std::string, double > constants
The list of constants.
Definition: table.h:3006
o2scl::table_units::clear_table
virtual void clear_table()
Clear the table and the column names and units (but leave constants)
Definition: table_units.h:500
o2scl::exc_efailed
@ exc_efailed
generic failure
Definition: err_hnd.h:61
o2scl::table_units::cup
convert_units< double > * cup
The pointer to the convert units object.
Definition: table_units.h:896
O2SCL_ERR2
#define O2SCL_ERR2(d, d2, n)
Set an error, two-string version.
Definition: err_hnd.h:281
o2scl::table_units::table_units
table_units(const table_units &t)
Copy with constructor from table_units.
Definition: table_units.h:106
o2scl::table_units::set_unit
void set_unit(std::string scol, std::string unit)
Set the unit for column scol to unit.
Definition: table_units.h:405
o2scl_cgs::cup
const double cup
cm^3
Definition: constants.h:300
o2scl
The main O<span style='position: relative; top: 0.3em; font-size: 0.8em'>2</span>scl O$_2$scl names...
Definition: anneal.h:42
o2scl::table::col::dat
vec_t dat
Pointer to column.
Definition: table.h:3016
o2scl::exc_enotfound
@ exc_enotfound
Generic "not found" result.
Definition: err_hnd.h:117
o2scl::table_units::remove_unit
void remove_unit(std::string scol)
Remove the unit for column scol.
Definition: table_units.h:386
o2scl::table::col::index
int index
Column index.
Definition: table.h:3018
o2scl::stod
double stod(std::string s)
Convert a string to a double.
o2scl::lib_settings_class::get_convert_units
convert_units< double > & get_convert_units()
Get the global convert_units object.
Definition: lib_settings.h:167
o2scl::table_units::convert_to_unit
int convert_to_unit(std::string scol, std::string unit, bool err_on_fail=true)
Convert the units of column scol to unit.
Definition: table_units.h:424
o2scl_hdf::hdf_input
void hdf_input(hdf_file &hf, o2scl::table< vec_t > &t, std::string name)
Input a o2scl::table object from a hdf_file.
Definition: hdf_io.h:148
o2scl::table_units::insert_table
void insert_table(table_units< vec2_t > &source, std::string src_index, bool allow_extrap=true, std::string dest_index="")
Insert columns from a source table into the new table by interpolation (or extrapolation)
Definition: table_units.h:828
o2scl::table::col
Column structure for table [protected].
Definition: table.h:3013
o2scl::table_units::type
virtual const char * type()
Return the type, "table_units".
Definition: table_units.h:616
o2scl::table_units
Data table table class with units.
Definition: table_units.h:42
o2scl::screenify
void screenify(size_t nin, const string_arr_t &in_cols, std::vector< std::string > &out_cols, size_t max_size=80)
Reformat the columns for output of width size.
Definition: misc.h:200
o2scl::table_units::rename_column
virtual void rename_column(std::string src, std::string dest)
Rename column named src to dest .
Definition: table_units.h:549
o2scl::table::end
aiter end()
Return the end of the column tree.
Definition: table.h:3089
o2scl::o2scl_settings
lib_settings_class o2scl_settings
The global library settings object.
o2scl::table_units::get_unit
std::string get_unit(size_t i) const
Get the unit for column with index i.
Definition: table_units.h:381
o2scl::success
@ success
Success.
Definition: err_hnd.h:47
o2scl::exc_einval
@ exc_einval
invalid argument supplied by user
Definition: err_hnd.h:59
o2scl::table_units::get_nunits
size_t get_nunits()
Return the number of columns with units.
Definition: table_units.h:469
o2scl::table_units::read_generic
virtual int read_generic(std::istream &fin, int verbose=0)
Clear the current table and read from a generic data file.
Definition: table_units.h:654
o2scl_hdf
The O<span style='position: relative; top: 0.3em; font-size: 0.8em'>2</span>scl O$_2$scl namespace ...
Definition: table.h:59
o2scl::table_units::table_units
table_units(const table< vec_t > &t)
Copy with constructor from table.
Definition: table_units.h:151
o2scl::table_units::operator=
table_units & operator=(const table_units &t)
Copy with operator= from table_units.
Definition: table_units.h:194
o2scl::table::aiter
std::map< std::string, col, std::greater< std::string > >::iterator aiter
Map iterator type.
Definition: table.h:3042
o2scl::table::aciter
std::map< std::string, col, std::greater< std::string > >::const_iterator aciter
Const map iterator type.
Definition: table.h:3046
o2scl::table_units::summary
virtual void summary(std::ostream *out, size_t ncol=79) const
Output a summary of the information stored.
Definition: table_units.h:557
o2scl::table::aviter
std::vector< aiter >::iterator aviter
Vector iterator type.
Definition: table.h:3048
o2scl::table::get_ncolumns
size_t get_ncolumns() const
Return the number of columns.
Definition: table.h:452
o2scl_hdf::hdf_input_data
void hdf_input_data(hdf_file &hf, o2scl::table< vec_t > &t)
Internal function for inputting a o2scl::table object.
Definition: hdf_io.h:186
o2scl_hdf::hdf_file
Store data in an O<span style='position: relative; top: 0.3em; font-size: 0.8em'>2</span>scl O$_2$sc...
Definition: hdf_file.h:105
o2scl::exc_esanity
@ exc_esanity
sanity check failed - shouldn't happen
Definition: err_hnd.h:65
o2scl::table_units::utree
std::map< std::string, std::string, std::greater< std::string > > utree
Unit map.
Definition: table_units.h:907
o2scl::convert_units< double >
O2SCL_ERR
#define O2SCL_ERR(d, n)
Set an error with message d and code n.
Definition: err_hnd.h:273
o2scl::table_units::table_units
table_units(int cmaxlines=0)
Create a new table_units with space for nlines<=cmaxlines.
Definition: table_units.h:95
o2scl::table_units::delete_column
virtual void delete_column(std::string scol)
Delete column named scol.
Definition: table_units.h:513
o2scl::table_units::copy_rows
void copy_rows(std::string func, table_units< vec2_t > &dest)
Copy all rows matching a particular condition to a new table.
Definition: table_units.h:312
o2scl::table::get
double get(std::string scol, size_t row) const
Get value from row row of column named col. .
Definition: table.h:408
o2scl::table::rename_column
virtual void rename_column(std::string src, std::string dest)
Rename column named src to dest .
Definition: table.h:857
o2scl::table::get_interp_type
size_t get_interp_type() const
Get the interpolation type.
Definition: table.h:1683
o2scl::szttos
std::string szttos(size_t x)
Convert a size_t to a string.
o2scl::table_units::operator=
table_units & operator=(const table< vec_t > &t)
Copy with operator= from table.
Definition: table_units.h:249
o2scl::table::get_column_name
std::string get_column_name(size_t icol) const
Returns the name of column col .
Definition: table.h:819

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).