23 #ifndef O2SCL_TABLE_UNITS_H
24 #define O2SCL_TABLE_UNITS_H
30 #include <o2scl/table.h>
31 #include <o2scl/lib_settings.h>
38 #ifndef DOXYGEN_NO_O2NS
70 #ifndef DOXYGEN_NO_O2NS
84 template<
class vec_t=std::vector<
double> >
85 class table_units :
public table<vec_t> {
89 #ifdef O2SCL_NEVER_DEFINED
109 this->constants=t.constants;
112 this->itype=t.get_interp_type();
115 this->nlines=t.get_nlines();
116 this->maxlines=this->nlines;
117 for(
size_t i=0;i<t.get_ncolumns();i++) {
120 std::string cname=t.get_column_name(i);
124 s.
dat.resize(this->nlines);
125 s.
index=this->atree.size();
126 this->atree.insert(make_pair(cname,s));
130 this->alist.push_back(it);
133 utree.insert(make_pair(cname,t.get_unit(cname)));
136 for(
size_t j=0;j<t.get_nlines();j++) {
137 it->second.dat[j]=t.get(cname,j);
142 this->intp_set=
false;
161 this->maxlines=this->nlines;
169 s.
dat.resize(this->nlines);
170 s.
index=this->atree.size();
171 this->atree.insert(make_pair(cname,s));
175 this->alist.push_back(it);
179 it->second.dat[j]=t.
get(cname,j);
184 this->intp_set=
false;
201 this->constants=t.constants;
204 this->itype=t.get_interp_type();
207 this->nlines=t.get_nlines();
208 this->maxlines=this->nlines;
209 for(
size_t i=0;i<t.get_ncolumns();i++) {
212 std::string cname=t.get_column_name(i);
216 s.
dat.resize(this->nlines);
217 s.
index=this->atree.size();
218 this->atree.insert(make_pair(cname,s));
222 this->alist.push_back(it);
225 utree.insert(make_pair(cname,t.get_unit(cname)));
228 for(
size_t j=0;j<t.get_nlines();j++) {
229 it->second.dat[j]=t.get(cname,j);
234 if (this->intp_set) {
235 this->intp_set=
false;
263 this->maxlines=this->nlines;
271 s.
dat=
new vec_t(this->nlines);
272 s.
index=this->atree.size();
273 this->atree.insert(make_pair(cname,s));
277 this->alist.push_back(it);
281 (*it->second.dat)[j]=t.
get(cname,j);
286 if (this->intp_set) {
287 this->intp_set=
false;
311 template<
class vec2_t>
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);
320 dest.set_unit(cname,get_unit(cname));
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);
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));
344 uciter it=utree.find(scol);
345 if (it==utree.end()) {
348 if (at==this->atree.
end()) {
349 O2SCL_ERR((((std::string)
"Column '")+scol+
350 "' not found in table_units::get_unit().").c_str(),
365 std::istringstream is(unit_line);
367 while(is >> unitval) {
368 if (unitval!=std::string(
".")) {
369 this->set_unit(this->get_column_name(icol),unitval);
382 return get_unit(this->get_column_name(i));
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(),
395 if (utree.size()==0) {
396 O2SCL_ERR(
"No units specified in table_units::remove_unit().",
405 void set_unit(std::string scol, std::string unit) {
407 uiter it=utree.find(scol);
408 if (it==utree.end()) {
410 if (at==this->atree.
end()) {
411 O2SCL_ERR((((std::string)
"Column '")+scol+
412 "' not found in table_units::set_unit().").c_str(),
415 utree.insert(make_pair(scol,unit));
425 bool err_on_fail=
true) {
428 uiter it=utree.find(scol);
429 if (it==utree.end()) {
431 O2SCL_ERR((((std::string)
"Column '")+scol+
"' not found in "+
432 "table_units::convert_to_unit().").c_str(),
440 if (it->second==unit)
return success;
444 if (at==this->atree.
end()) {
446 O2SCL_ERR((((std::string)
"Column '")+scol+
"' not found in "+
447 "table_units::convert_to_unit().").c_str(),
455 vec_t &vec=at->second.dat;
456 double conv=
cup->convert(it->second,unit,1.0);
458 for(
size_t i=0;i<this->get_nlines();i++) {
505 if (this->intp_set==
true) {
507 this->intp_set=
false;
517 if (it==this->atree.
end()) {
518 O2SCL_ERR((((std::string)
"Column '")+scol+
519 " not found in table_units::delete_column().").c_str(),
525 if (get_unit(scol).length()>0) remove_unit(scol);
529 vit+=it->second.index;
534 this->alist[this->alist.size()-1]->second.index=it->second.index;
537 this->atree.erase(it);
538 this->alist.erase(vit);
550 std::string unit=get_unit(src);
557 virtual void summary(std::ostream *out,
size_t ncol=79)
const {
559 if (this->constants.size()==1) {
560 (*out) <<
"1 constant:" << std::endl;
562 (*out) << this->constants.size() <<
" constants:" << std::endl;
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;
570 size_t nh=this->get_ncolumns(), nh2;
574 (*out) <<
"No columns." << std::endl;
579 (*out) <<
"1 column: " << std::endl;
581 (*out) << nh <<
" columns: " << std::endl;
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))+
"]";
589 std::vector<std::string> h2;
595 for(
size_t i=0;i<nh2;i++) {
596 (*out) << h2[i] << std::endl;
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;
608 (*out) << this->get_nlines() <<
" lines of data." << std::endl;
616 virtual const char *
type() {
return "table_units"; }
627 if (!this->is_column(dest)) this->new_column(dest);
629 typedef typename std::map<std::string,
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(),
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(),
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];
659 std::istringstream *is;
662 std::vector<std::string> onames, nnames;
664 is=
new std::istringstream(line);
665 while ((*is) >> stemp) {
666 onames.push_back(stemp);
668 std::cout <<
"Read possible column name: " << stemp << std::endl;
675 for(
size_t i=0;i<onames.size();i++) {
681 if (n_nums==onames.size()) {
684 std::cout <<
"First row looks like it contains numerical values."
686 std::cout <<
"Creating generic column names: ";
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] <<
" ";
694 if (verbose>0) std::cout << std::endl;
697 for(
size_t i=0;i<nnames.size();i++) {
698 this->new_column(nnames[i]);
702 this->set_nlines_auto(irow+1);
703 for(
size_t i=0;i<onames.size();i++) {
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;
723 for(
size_t i=0;i<nnames.size();i++) {
724 this->new_column(nnames[i]);
728 std::vector<std::string> units;
730 is=
new std::istringstream(line);
732 while ((*is) >> stemp) {
733 units.push_back(stemp);
734 if (stemp[0]==
'[') num_units++;
736 std::cout <<
"Read word in second row: " << stemp << std::endl;
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;
748 if (num_units==((
int)units.size()) || num_units>2) {
750 std::cout <<
"Looks like second row contains units." << std::endl;
752 for(
size_t i=0;i<units.size();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);
760 set_unit(nnames[i],stemp);
762 std::cout <<
"Name,unit: " << nnames[i] <<
" [" << stemp <<
"]"
770 this->set_nlines_auto(1);
771 for(
size_t i=0;i<units.size();i++) {
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++) {
786 this->set(i,irow,data);
827 template<
class vec2_t>
829 bool allow_extrap=
true, std::string dest_index=
"") {
831 if (dest_index==
"") dest_index=src_index;
833 if (!source.is_column(src_index)) {
836 if (!this->is_column(dest_index)) {
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);
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);
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]));
876 friend void o2scl_hdf::hdf_output
882 friend void o2scl_hdf::hdf_output_data
890 #ifndef DOXYGEN_INTERNAL
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;
907 std::map<std::string,std::string,std::greater<std::string> >
utree;
918 template<
class vec_t>
923 std::vector<double> dbuffer;
929 for(
size_t i=0;i<t.get_nconsts();i++) {
932 t.get_constant(i,name,val);
934 if (i<t.get_nconsts()-1) {
937 dbuffer.push_back(val);
940 ibuffer=cbuffer.length();
943 MPI_Send(&ibuffer,1,MPI_INT,dest_rank,
946 MPI_Send(&(cbuffer[0]),cbuffer.length(),MPI_CHAR,dest_rank,
949 MPI_Send(&(dbuffer[0]),dbuffer.size(),MPI_DOUBLE,dest_rank,
957 for(
size_t i=0;i<t.get_ncolumns();i++) {
958 std::string name=t.get_column_name(i);
960 if (i<t.get_ncolumns()-1) {
965 ibuffer=cbuffer.length();
967 MPI_Send(&ibuffer,1,MPI_INT,dest_rank,
970 MPI_Send(&(cbuffer[0]),cbuffer.length(),MPI_CHAR,dest_rank,
977 for(
size_t i=0;i<t.get_ncolumns();i++) {
978 std::string unit=t.
get_unit(t.get_column_name(i));
980 if (i<t.get_ncolumns()-1) {
985 ibuffer=cbuffer.length();
987 MPI_Send(&ibuffer,1,MPI_INT,dest_rank,
990 MPI_Send(&(cbuffer[0]),cbuffer.length(),MPI_CHAR,dest_rank,
998 ibuffer=t.get_interp_type();
999 MPI_Send(&ibuffer,1,MPI_INT,dest_rank,
1000 tag,MPI_COMM_WORLD);
1005 ibuffer=t.get_nlines();
1007 MPI_Send(&ibuffer,1,MPI_INT,dest_rank,
1008 tag,MPI_COMM_WORLD);
1010 for(
size_t i=0;i<t.get_ncolumns();i++) {
1012 MPI_Send(&(t[i][0]),t.get_nlines(),MPI_DOUBLE,dest_rank,
1013 tag,MPI_COMM_WORLD);
1022 template<
class vec_t>
1023 void o2scl_table_mpi_recv(
size_t src_rank,
1028 std::vector<char> cbuffer;
1029 std::vector<double> dbuffer;
1031 std::vector<std::string> names;
1039 MPI_Recv(&ibuffer,1,MPI_INT,src_rank,tag,MPI_COMM_WORLD,
1041 cbuffer.resize(ibuffer);
1043 MPI_Recv(&(cbuffer[0]),ibuffer,MPI_CHAR,src_rank,tag,MPI_COMM_WORLD,
1047 for(
size_t i=0;i<cbuffer.size();i++) {
1048 if (cbuffer[i]!=
' ') {
1051 if (stemp.size()>0) {
1052 names.push_back(stemp);
1057 if (stemp.size()>0) {
1058 names.push_back(stemp);
1063 dbuffer.resize(names.size());
1066 MPI_Recv(&(dbuffer[0]),dbuffer.size(),MPI_DOUBLE,
1067 src_rank,tag,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
1070 for(
size_t i=0;i<names.size();i++) {
1071 t.add_constant(names[i],dbuffer[i]);
1080 MPI_Recv(&ibuffer,1,MPI_INT,src_rank,tag,MPI_COMM_WORLD,
1082 cbuffer.resize(ibuffer);
1084 MPI_Recv(&(cbuffer[0]),ibuffer,MPI_CHAR,src_rank,tag,MPI_COMM_WORLD,
1088 for(
size_t i=0;i<cbuffer.size();i++) {
1089 if (cbuffer[i]!=
' ') {
1092 if (stemp.size()>0) {
1093 names.push_back(stemp);
1098 if (stemp.size()>0) {
1099 names.push_back(stemp);
1103 for(
size_t i=0;i<names.size();i++) {
1104 t.new_column(names[i]);
1112 MPI_Recv(&ibuffer,1,MPI_INT,src_rank,tag,MPI_COMM_WORLD,
1114 cbuffer.resize(ibuffer);
1116 MPI_Recv(&(cbuffer[0]),ibuffer,MPI_CHAR,src_rank,tag,MPI_COMM_WORLD,
1120 for(
size_t i=0;i<cbuffer.size();i++) {
1121 if (cbuffer[i]!=
' ') {
1124 if (stemp.size()>0) {
1125 names.push_back(stemp);
1130 if (stemp.size()>0) {
1131 names.push_back(stemp);
1135 for(
size_t i=0;i<names.size();i++) {
1136 t.
set_unit(t.get_column_name(i),names[i]);
1144 MPI_Recv(&ibuffer,1,MPI_INT,src_rank,tag,MPI_COMM_WORLD,
1146 t.set_interp_type(ibuffer);
1152 MPI_Recv(&ibuffer,1,MPI_INT,src_rank,tag,MPI_COMM_WORLD,
1154 t.set_nlines(ibuffer);
1156 for(
size_t i=0;i<t.get_ncolumns();i++) {
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);
1169 #ifndef DOXYGEN_NO_O2NS