Go to the documentation of this file.00001 #include "mbl_table.h"
00002
00003
00004
00005
00006
00007
00008 #include <vcl_cstdlib.h>
00009 #include <vcl_iostream.h>
00010 #include <vcl_cmath.h>
00011
00012
00013
00014 static double tolerance_ = 1e-15;
00015
00016
00017 static bool fractional_tolerance_ = false;
00018
00019
00020 static int verbosity_ = 0;
00021
00022
00023
00024
00025
00026 mbl_table::mbl_table(const char delim)
00027 : delimiter_(delim)
00028 {
00029 }
00030
00031
00032
00033
00034
00035 mbl_table::mbl_table(const char delim,
00036 const vcl_vector<vcl_string>& headers)
00037 : delimiter_(delim),
00038 column_headers_(headers)
00039 {
00040 unsigned ncols = column_headers_.size();
00041
00042
00043 columns_.resize(ncols);
00044
00045
00046 for (unsigned int c=0; c<ncols; ++c)
00047 {
00048 header_to_column_index_[headers[c]] = c;
00049 }
00050 }
00051
00052
00053
00054
00055
00056 unsigned mbl_table::num_cols() const
00057 {
00058 return columns_.size();
00059 }
00060
00061
00062
00063
00064
00065 unsigned mbl_table::num_rows() const
00066 {
00067 int nrows=0;
00068
00069 if (columns_.size()>0) nrows=columns_[0].size();
00070 return nrows;
00071 }
00072
00073
00074
00075
00076
00077 bool mbl_table::column_exists(const vcl_string& header) const
00078 {
00079
00080 vcl_map<vcl_string, unsigned>::const_iterator iter =
00081 header_to_column_index_.find(header);
00082
00083 return iter != header_to_column_index_.end();
00084 }
00085
00086
00087
00088
00089 bool mbl_table::get_column(const vcl_string& header,
00090 vcl_vector<double>& column) const
00091 {
00092 bool success = false;
00093 column.clear();
00094
00095
00096 vcl_map<vcl_string, unsigned>::const_iterator iter =
00097 header_to_column_index_.find(header);
00098
00099 if (iter != header_to_column_index_.end())
00100 {
00101
00102 column = columns_[iter->second];
00103 success = true;
00104 }
00105 else
00106 {
00107 vcl_cerr << "ERROR: mbl_table::get_column(): column \""
00108 << header << "\" does not exist in the table.\n";
00109 }
00110
00111 return success;
00112 }
00113
00114
00115
00116
00117
00118 bool mbl_table::get_row(const unsigned& r,
00119 vcl_vector<double>& row) const
00120 {
00121
00122 row.clear();
00123
00124
00125 if (r < num_rows())
00126 {
00127 unsigned int ncols = num_cols();
00128 row.resize(ncols);
00129 for (unsigned c=0; c<ncols; ++c)
00130 {
00131 row[c] = columns_[c][r];
00132 }
00133 return true;
00134 }
00135 else
00136 {
00137 vcl_cerr << "ERROR: mbl_table::get_row(): row "
00138 << r << " does not exist in the table.\n";
00139 return false;
00140 }
00141 }
00142
00143
00144
00145
00146
00147 void mbl_table::get_column_headers(vcl_vector<vcl_string>& headers) const
00148 {
00149 headers = column_headers_;
00150 }
00151
00152
00153
00154
00155
00156 bool mbl_table::set_element(const vcl_string& header,
00157 const unsigned r,
00158 const double value)
00159 {
00160 bool success = false;
00161
00162
00163 vcl_map<vcl_string, unsigned>::const_iterator iter =
00164 header_to_column_index_.find(header);
00165
00166 if (iter != header_to_column_index_.end())
00167 {
00168
00169 vcl_vector<double>& col = columns_[iter->second];
00170 if (col.size()>r)
00171 {
00172
00173 col[r] = value;
00174 success = true;
00175 }
00176 else
00177 {
00178 vcl_cerr << "ERROR: mbl_table::set_element(): row "
00179 << r << " does not exist in the table.\n";
00180 }
00181 }
00182 else
00183 {
00184 vcl_cerr << "ERROR: mbl_table::set_element(): column \""
00185 << header << "\" does not exist in the table.\n";
00186 }
00187
00188 return success;
00189 }
00190
00191
00192
00193
00194
00195 double mbl_table::get_element(const vcl_string& header,
00196 const unsigned r,
00197 bool* success) const
00198 {
00199 double value = 1e-19;
00200 if (success)
00201 *success = false;
00202
00203
00204 vcl_map<vcl_string, unsigned>::const_iterator iter =
00205 header_to_column_index_.find(header);
00206
00207 if (iter != header_to_column_index_.end())
00208 {
00209
00210 const vcl_vector<double>& col = columns_[iter->second];
00211 if (col.size()>r)
00212 {
00213
00214 value = col[r];
00215 if (success)
00216 *success = true;
00217 }
00218 else
00219 {
00220 vcl_cerr << "ERROR: mbl_table::get_element(): row "
00221 << r << " does not exist in the table.\n";
00222 }
00223 }
00224 else
00225 {
00226 vcl_cerr << "ERROR: mbl_table::get_element(): column \""
00227 << header << "\" does not exist in the table.\n";
00228 }
00229
00230 return value;
00231 }
00232
00233
00234
00235
00236
00237 bool mbl_table::append_column(const vcl_string& header,
00238 const vcl_vector<double>& column)
00239 {
00240
00241 if (header_to_column_index_.find(header) == header_to_column_index_.end())
00242 {
00243
00244 if (num_rows()==0 || num_rows()==column.size())
00245 {
00246 column_headers_.push_back(header);
00247 columns_.push_back(column);
00248 header_to_column_index_[header] = columns_.size()-1;
00249 return true;
00250 }
00251 else
00252 {
00253 vcl_cerr << "ERROR: mbl_table::append_column(): "
00254 << "new column is different length from existing columns.\n"
00255 << "Column not appended.\n";
00256 return false;
00257 }
00258 }
00259 else
00260 {
00261 vcl_cerr << "ERROR: mbl_table::append_column(): a column with header \""
00262 << header << "\" already exists.\n"
00263 << "Column not appended.\n";
00264 return false;
00265 }
00266 }
00267
00268
00269
00270
00271
00272 bool mbl_table::append_column(const vcl_string& header,
00273 const double val)
00274 {
00275
00276 if (header_to_column_index_.find(header) == header_to_column_index_.end())
00277 {
00278
00279 column_headers_.push_back(header);
00280 unsigned c = columns_.size();
00281 header_to_column_index_[header] = c;
00282 columns_.push_back(vcl_vector<double>());
00283 columns_[c].resize(num_rows(), val);
00284 return true;
00285 }
00286 else
00287 {
00288 vcl_cerr << "ERROR: mbl_table::append_column(): a column with header \""
00289 << header << "\" already exists.\n"
00290 << "Column not appended.\n";
00291 return false;
00292 }
00293 }
00294
00295
00296
00297
00298
00299 bool mbl_table::append_row(const vcl_vector<double>& row)
00300 {
00301
00302 unsigned ncols = num_cols();
00303 if (ncols==row.size())
00304 {
00305 for (unsigned c=0; c<ncols; ++c)
00306 {
00307 columns_[c].push_back(row[c]);
00308 }
00309 return true;
00310 }
00311 else
00312 {
00313 vcl_cerr << "ERROR: mbl_table::append_row(): "
00314 << "new row is different length from existing row.\n"
00315 << "Row not appended.\n";
00316 return false;
00317 }
00318 }
00319
00320
00321
00322
00323
00324 bool mbl_table::append_row(const double val)
00325 {
00326
00327 unsigned ncols = num_cols();
00328 for (unsigned c=0; c<ncols; ++c)
00329 {
00330 columns_[c].push_back(val);
00331 }
00332
00333 return true;
00334 }
00335
00336
00337
00338
00339
00340 bool mbl_table::read(vcl_istream& is)
00341 {
00342 bool success = false;
00343
00344 if (is.good() && !is.eof())
00345 {
00346
00347 bool eol = false;
00348 bool eof = false;
00349 unsigned col = 0;
00350 while (!eol && !eof)
00351 {
00352 vcl_string str;
00353 if (read_delimited_string(is, str, eol, eof))
00354 {
00355
00356 column_headers_.push_back(str);
00357 header_to_column_index_[str] = col;
00358 columns_.push_back(vcl_vector<double>(0));
00359
00360 col++;
00361 }
00362 }
00363
00364
00365 while (!is.eof())
00366 {
00367
00368 eol = false;
00369 eof = false;
00370 unsigned col = 0;
00371
00372 while (!eol && !eof)
00373 {
00374 vcl_string str;
00375 if (read_delimited_string(is, str, eol, eof))
00376 {
00377
00378 double val = vcl_atof(str.c_str());
00379
00380
00381 columns_[col].push_back(val);
00382
00383
00384 col++;
00385 if (col==num_cols()) col = 0;
00386 }
00387 }
00388 }
00389
00390 success = true;
00391 }
00392
00393 return success;
00394 }
00395
00396
00397
00398
00399
00400 void mbl_table::write(vcl_ostream& os) const
00401 {
00402
00403 unsigned int ncols = num_cols();
00404
00405
00406 unsigned int nrows = num_rows();
00407
00408
00409 for (unsigned c=0; c<ncols; ++c)
00410 {
00411 os << column_headers_[c] << delimiter_;
00412 }
00413 os << '\n';
00414
00415
00416 for (unsigned r=0; r<nrows; ++r)
00417 {
00418 for (unsigned c=0; c<ncols; ++c)
00419 {
00420 os << columns_[c][r] << delimiter_;
00421 }
00422 os << '\n';
00423 }
00424 }
00425
00426
00427
00428 bool mbl_table::subtable(mbl_table &new_table, const vcl_vector<vcl_string> &headers) const
00429 {
00430 bool ret = true;
00431
00432 new_table = mbl_table();
00433
00434
00435
00436 for (unsigned c=0; c<headers.size(); ++c)
00437 {
00438
00439 vcl_map<vcl_string, unsigned>::const_iterator iter =
00440 header_to_column_index_.find(headers[c]);
00441
00442 if (iter != header_to_column_index_.end())
00443 {
00444 new_table.append_column(headers[c],columns_[iter->second]);
00445 }
00446 else
00447 {
00448 ret=false;
00449 }
00450 }
00451
00452 return ret;
00453 }
00454
00455
00456
00457
00458
00459 bool mbl_table::read_delimited_string(vcl_istream& is,
00460 vcl_string& str,
00461 bool& eol,
00462 bool& eof)
00463 {
00464 str = "";
00465 eol = false;
00466 bool success = false;
00467
00468 char c = 0;
00469 bool eos = false;
00470 while (!eos && is.good() && !is.eof())
00471 {
00472 is.get(c);
00473 if (c=='\n')
00474 {
00475 eol = true;
00476 eos = true;
00477 }
00478 else if (c==delimiter_)
00479 {
00480 eos = true;
00481 }
00482 else if (c==0)
00483 {
00484 eof = true;
00485 }
00486 else
00487 {
00488 str += c;
00489 }
00490 }
00491
00492 if (eos && str.length()>0)
00493 {
00494 success = true;
00495 }
00496
00497 return success;
00498 }
00499
00500
00501
00502
00503
00504 bool mbl_table::operator==(const mbl_table& rhs) const
00505 {
00506
00507 if (this == &rhs)
00508 {
00509 if (verbosity_>0)
00510 vcl_cout << "Both tables are actually the same memory object!" << vcl_endl;
00511 return true;
00512 }
00513
00514
00515 if (delimiter_ != rhs.delimiter_)
00516 {
00517 if (verbosity_>0)
00518 vcl_cout << "Tables have different delimiter characters" << vcl_endl;
00519 return false;
00520 }
00521
00522
00523 if (column_headers_ != rhs.column_headers_)
00524 {
00525 if (verbosity_>0)
00526 vcl_cout << "Tables have different column headers" << vcl_endl;
00527 return false;
00528 }
00529
00530
00531 if (header_to_column_index_ != rhs.header_to_column_index_)
00532 {
00533 if (verbosity_>0)
00534 vcl_cout << "Tables have different header-to-column index map" << vcl_endl;
00535 return false;
00536 }
00537
00538
00539 unsigned ncols = columns_.size();
00540 if (ncols != rhs.columns_.size())
00541 {
00542 if (verbosity_>0)
00543 vcl_cout << "Tables have different number of columns" << vcl_endl;
00544 return false;
00545 }
00546
00547
00548 bool values_different = false;
00549 for (unsigned c=0; c<ncols; ++c)
00550 {
00551
00552 unsigned nrows = columns_[c].size();
00553 if (nrows != rhs.columns_[c].size())
00554 {
00555 if (verbosity_>0)
00556 vcl_cout << "Tables have different number of elements in some columns"
00557 << vcl_endl;
00558 return false;
00559 }
00560
00561
00562 for (unsigned r=0; r<nrows; ++r)
00563 {
00564 double diff = columns_[c][r] - rhs.columns_[c][r];
00565 if (fractional_tolerance_)
00566 {
00567 diff /= columns_[c][r];
00568 }
00569 if (vcl_fabs(diff) > tolerance_)
00570 {
00571 if (verbosity_>0)
00572 vcl_cout << "Tables have different values in column " << c
00573 << " (" << column_headers_[c] << "), row " << r
00574 << ": " << columns_[c][r] << ", "
00575 << rhs.columns_[c][r]
00576 << " (diff=" << diff << ") "
00577 << vcl_endl;
00578
00579 if (verbosity_<=1)
00580 return false;
00581 else
00582 values_different = true;
00583 }
00584 }
00585 }
00586 if (values_different) return false;
00587
00588
00589 return true;
00590 }
00591
00592
00593
00594
00595
00596 bool mbl_table::operator!=(const mbl_table& rhs) const
00597 {
00598 return !(*this==rhs);
00599 }
00600
00601
00602
00603
00604
00605 void mbl_table::set_tolerance(const double& tol,
00606 const bool& fract)
00607 {
00608 tolerance_ = tol;
00609 fractional_tolerance_ = fract;
00610 }
00611
00612
00613
00614
00615
00616 void mbl_table::set_verbosity(const int& v)
00617 {
00618 verbosity_ = v;
00619 }