contrib/mul/mbl/mbl_table.h
Go to the documentation of this file.
00001 #ifndef mbl_table_h
00002 #define mbl_table_h
00003 //:
00004 // \file
00005 // \author Kevin de Souza
00006 // \date 05-Aug-2004
00007 // \brief Container for tabulated data suitable for reading/writing to delimited text files
00008 
00009 #include <vcl_map.h>
00010 #include <vcl_iosfwd.h>
00011 #include <vcl_vector.h>
00012 #include <vcl_string.h>
00013 
00014 //: Container for tabulated data suitable for reading/writing to delimited text files.
00015 //
00016 // Table comprises a number of columns of double-precision data.
00017 // Each column is headed by a text string (which may contain whitespace but not end-of-line).
00018 // Column headers must be unique.
00019 // Columns are separated by a delimiter character (e.g. "\t").
00020 // The delimiter character must not occur in any of the entries!
00021 // The delimiter character is optional at the end of a row.
00022 // Each row must be terminated by an end-of-line (including the last row).
00023 // Each column of data is stored as a vector of doubles and associated with the column header string.
00024 class mbl_table
00025 {
00026 public:
00027 
00028   //: Constructor
00029   // \param delim The delimiter character.
00030   mbl_table(const char delim='\t');
00031 
00032 
00033   //: Constructor
00034   // \param delim The delimiter character.
00035   // \param headers The column headers (in order).
00036   mbl_table(const char delim,
00037             const vcl_vector<vcl_string>& headers);
00038 
00039   
00040   //: Return the number of columns
00041   unsigned num_cols() const;
00042 
00043   
00044   //: Return the number of rows
00045   unsigned num_rows() const;
00046 
00047 
00048   //: Get the column of data corresponding to a particular heading.
00049   // \param header String identifying the desired column.
00050   // \return true if there is a column with the specified heading.
00051   // \retval column A vector containing the values of the requested column.
00052   bool get_column(const vcl_string& header,
00053                   vcl_vector<double>& column) const;
00054 
00055 
00056   //: Returns true if column exists
00057   bool column_exists(const vcl_string& header) const;
00058   
00059 
00060   //: Get a specified row of data.
00061   // \param r Index of the desired row.
00062   // \return true if there is a row with the specified index.
00063   // \retval row A vector containing the values of the requested row.
00064   bool get_row(const unsigned& r,
00065                vcl_vector<double>& row) const;
00066 
00067   
00068   //: Get the list of column headers (in column order).
00069   // \retval headers The list of column headers.
00070   void get_column_headers(vcl_vector<vcl_string>& headers) const;
00071 
00072 
00073   //: Append a column of data with its own heading.
00074   // \param header String identifying the column.
00075   // \param column A vector containing the values of the column.
00076   // \return true If the column was added.
00077   // \note The new column must be the same length as existing columns.
00078   bool append_column(const vcl_string& header,
00079                      const vcl_vector<double>& column);
00080   
00081 
00082   //: Append an empty column with its own heading.
00083   // \param header String identifying the column.
00084   // \param val Default value to initialize all elements of the new column.
00085   // \return true If the column was added.
00086   // \note The new column will be the same length as existing columns.
00087   bool append_column(const vcl_string& header,
00088                      const double val=0);
00089   
00090 
00091   //: Append a row of data.
00092   // \return true if the row was added.
00093   // \param row A vector containing the values of the new row.
00094   // \note The new row must be the same length as existing rows.
00095   bool append_row(const vcl_vector<double>& row);
00096   
00097 
00098   //: Append an empty row.
00099   // \return true If the row was added.
00100   // \param val Default value to initialize all elements of the new row.
00101   // \note The new row will be the same length as existing rows.
00102   bool append_row(const double val=0);
00103   
00104 
00105   //: Set the value of an existing element.
00106   // \param header The string identifying the column to be modified.
00107   // \param r The row index of the element to be modified.
00108   // \param value The new value to use for the modified element.
00109   // \return False if the column does not exist or the row index is not valid.
00110   // \note This function is intended only for existing elements.
00111   bool set_element(const vcl_string& header, 
00112                    const unsigned r, 
00113                    const double value);
00114 
00115 
00116   //: Get the value of an existing element.
00117   // \param header The string identifying the column of interest.
00118   // \param r The row index of the element of interest.
00119   // \return The value of the requested element (undefined if the element
00120   //         does not exist).
00121   // \retval success If provided, will be used to indicate whether the 
00122   //                 specified element existed.
00123   // \note This function is intended only for existing elements.
00124   // \note It is recommended that you provide and check the parameter success.
00125   double get_element(const vcl_string& header, 
00126                      const unsigned r, 
00127                      bool* success=0) const;
00128 
00129   
00130   //: Load this table's data from specified text stream.
00131   // Any existing data is lost.
00132   // \return true if table was read successfully from the stream.
00133   bool read(vcl_istream& is);
00134 
00135 
00136   //: Save this table's data to specified text stream.
00137   void write(vcl_ostream& os) const;
00138 
00139 
00140   //: Create a new table of subset of columns defined by headers
00141   // \retval new_table a subtable 
00142   // \param headers subset of column headers
00143   // \return true if all columns in headers existed in "this" and were copied
00144   bool subtable(mbl_table &new_table,  const vcl_vector<vcl_string> &headers) const;
00145 
00146   
00147   //: Is another table identical to this one?
00148   // \note The normal behaviour of this function is to return false as soon
00149   // as a discrepancy is found. However, if verbosity>=2 this function will
00150   // compare all corresponding elements (providing that the table dimensions match).
00151   bool operator==(const mbl_table& rhs) const;
00152 
00153   
00154   //: Is another table different from this one?
00155   // \sa operator==()
00156   bool operator!=(const mbl_table& rhs) const;
00157 
00158 
00159   //: Set the tolerance used to determine whether table entries are equal.
00160   // \param tol The tolerance should be a small positive number, eg 1e-19.
00161   // \param frac Whether the tolerance is applied as a fractional difference.
00162   static void set_tolerance(const double& tol,
00163                             const bool& fract=false);
00164 
00165 
00166   //: Set the level of verbosity used for error output.
00167   // \param v The verbosity should be a small integer, eg -3 to 3. 
00168   // Larger values cause more detailed output.
00169   // Default level is 0. 
00170   // \note Currently only levels 1 and 2 are defined: level 1 provides some
00171   // feedback for equality testing; level 2 also causes the equality operator
00172   // to check all corresponding elements of a table.
00173   static void set_verbosity(const int& v);
00174 
00175 
00176 protected:
00177 
00178   //: Read a series of characters from the stream until a delimiter character or eol.
00179   // \param is The input stream.
00180   // \return true if a non-empty string was successfully read.
00181   // \retval str The string which was read.
00182   // \retval eol Whether the stream is at end-of-line after reading the string.
00183   // \retval eof Whether the stream is at end-of-file after reading the string.
00184   bool read_delimited_string(vcl_istream& is,
00185                              vcl_string& str,
00186                              bool& eol,
00187                              bool& eof);
00188 
00189   //: The character delimiting each column.
00190   char delimiter_;
00191 
00192   //: The column headers (in order)
00193   vcl_vector<vcl_string> column_headers_;
00194 
00195   //: Map a column header string to column index
00196   vcl_map<vcl_string, unsigned> header_to_column_index_;
00197 
00198   //: The table data, arranged as column vectors of double data.
00199   vcl_vector<vcl_vector<double> > columns_;
00200 
00201 };
00202 
00203 #endif // mbl_table_h