17#include "IException.h" 
   24  LoadCSV::LoadCSV() : _base(), _csvSpecs(
"LoadCSV"), _data(0,0), _history() { }
 
   26  LoadCSV::LoadCSV(
const QString &base, 
const HiCalConf &conf,
 
   27                   const DbProfile &profile) : _base(), _csvSpecs(
"LoadCSV"),
 
   28                   _data(0,0), _history() {
 
   29    load(base, conf, profile);
 
   32  void LoadCSV::load(
const QString &base, 
const HiCalConf &conf,
 
   33                     const DbProfile &profile) {
 
   36    init(base, conf, profile);
 
   41    QString csvfile(conf.filepath(getValue()));
 
   42    addHistory(
"File", csvfile);
 
   46    bool colHeader(
IsEqual(
ConfKey(_csvSpecs,makeKey(
"Header"), QString(
"FALSE")), 
"TRUE"));
 
   47    bool rowHeader(colHeader);  
 
   48    if (
IsEqual(getValue(
"ColumnHeader"), 
"TRUE"))  colHeader = 
true;
 
   49    if (
IsEqual(getValue(
"RowHeader"), 
"TRUE"))  rowHeader = 
true;
 
   50    if (_csvSpecs.exists(makeKey(
"ColumnName"))) colHeader = 
true;
 
   51    if (_csvSpecs.exists(makeKey(
"RowName")   )) rowHeader = 
true;
 
   54    int skip = 
toInt(
ConfKey(_csvSpecs, makeKey(
"SkipLines"), QString(
"0")));
 
   55    addHistory(
"SkipLines", 
ToString(skip));
 
   56    bool comments = 
IsEqual(
ConfKey(_csvSpecs, makeKey(
"IgnoreComments"), QString(
"TRUE")));
 
   57    QString separator = 
ConfKey(_csvSpecs, makeKey(
"Separator"), QString(
","));
 
   58    if (separator.isEmpty()) separator = 
",";   
 
   61    csv.setComment(comments);
 
   63    csv.setHeader(colHeader);
 
   64    csv.setDelimiter(separator[0].toLatin1());
 
   65    if (separator[0] == 
' ') csv.setSkipEmptyParts();
 
   68    FileName csvF(csvfile);
 
   69    csvfile = csvF.expanded();
 
   72    } 
catch (IException &ie) {
 
   73      QString mess =  
"Could not read CSV file \'" + csvfile + 
"\'";
 
   74      throw IException(ie, IException::User, mess, _FILEINFO_);
 
   78    int ncols = csv.columns();
 
   79    int nrows = csv.rows();
 
   82    int startColumn((rowHeader) ? 1 : 0), endColumn(ncols-1);
 
   83    int startRow(0), endRow(nrows-1);
 
   86    QString colName(getValue(
"ColumnName"));
 
   87    if (!colName.isEmpty()) {
 
   88      addHistory(
"ColumnName", colName);
 
   89      CSVReader::CSVAxis chead = csv.getHeader();
 
   90      startColumn = getAxisIndex(colName, chead);
 
   91      if (startColumn < 0) {
 
   92        QString mess = 
"Column name " + colName +
 
   93                      " not found in CSV file " + csvfile;
 
   94        throw IException(IException::User, mess, _FILEINFO_);
 
   96      endColumn = startColumn;
 
   97      addHistory(
"ColumnIndex", 
ToString(startColumn));
 
   99    else if (!(getValue(
"ColumnIndex").isEmpty())) {
 
  100       startColumn = 
ToInteger(getValue(
"ColumnIndex")) +
 
  101                                 ((rowHeader) ? 1 : 0);
 
  102       endColumn = startColumn;
 
  103      addHistory(
"ColumnStart", 
ToString(startColumn));
 
  104      addHistory(
"ColumnEnd", 
ToString(endColumn));
 
  108    QString rowName(getValue(
"RowName"));
 
  109    if (!rowName.isEmpty()) {
 
  110      addHistory(
"RowName", rowName);
 
  112        QString mess = 
"Row name given but config does not specify presence of row header!";
 
  113        throw IException(IException::User, mess, _FILEINFO_);
 
  115      CSVReader::CSVAxis rhead = csv.getColumn(0);
 
  116      startRow = getAxisIndex(rowName, rhead);
 
  118        QString mess = 
"Row name " + rowName + 
" not found in CSV file " + csvfile;
 
  119        throw IException(IException::User, mess, _FILEINFO_);
 
  122      addHistory(
"RowIndex", 
ToString(startRow));
 
  124    else if (!(getValue(
"RowIndex").isEmpty())) {
 
  125       startRow = 
ToInteger(getValue(
"RowIndex"));
 
  126       if (rowHeader) startRow++;
 
  128      addHistory(
"RowStart", 
ToString(startRow));
 
  129      addHistory(
"RowEnd", 
ToString(endRow));
 
  133    int drows(endRow-startRow+1);
 
  134    int dcols(endColumn-startColumn+1);
 
  136    vector<QString> errors;
 
  137    for (
int r = startRow, hr = 0 ; r <= endRow ; r++, hr++) {
 
  138      CSVReader::CSVAxis row = csv.getRow(r);
 
  139      for (
int c = startColumn, hc = 0 ; c <= endColumn ; c++, hc++) {
 
  144          std::ostringstream mess;
 
  145          mess << 
"Invalid real value (" << row[c] << 
") in row index " << r;
 
  146          if (!rowName.isEmpty()) mess << 
" (Name:" << rowName << 
")";
 
  147          mess << 
", column index " << c;
 
  148          if (!colName.isEmpty()) mess << 
" (Name:" << colName << 
")";
 
  149          errors.push_back(mess.str().c_str());
 
  159    if (errors.size() > 0) {
 
  161      std::ostringstream mess;
 
  162      mess << 
"Conversion errors in CSV file " + csvfile + 
": Errors: ";
 
  164      std::vector<QString>::const_iterator it = errors.begin();
 
  166      while (it != errors.end()) {
 
  170      throw IException(IException::User, mess.str().c_str(), _FILEINFO_);
 
  176  QString LoadCSV::filename()
 const {
 
  180  int LoadCSV::size()
 const {
 
  181    return (_data.dim1() * _data.dim2());
 
  184  bool LoadCSV::validateSize(
const int &expected, 
const bool &throw_on_error)
 
  186    if (expected != size()) {
 
  187      if (!throw_on_error) 
return (
false);
 
  189      mess << 
"Invalid count (Expected: " << expected << 
", Received: " 
  190           << size() << 
") in CSV file " << getValue();
 
  191      throw IException(IException::User, mess.str(), _FILEINFO_);
 
  196  HiVector LoadCSV::getVector()
 const {
 
  197    HiVector v(size(), 
const_cast<double *
> (_data[0]));
 
  201  HiMatrix LoadCSV::getMatrix()
 const {
 
  202    return (_data.copy());
 
  206  void LoadCSV::History(HiHistory &history)
 const {
 
  207    std::ostringstream mess;
 
  210    for (
unsigned int i = 0 ; i < _history.size() ; i++) {
 
  211      mess << comma << _history[i];
 
  215    history.add(mess.str().c_str());
 
  219  void LoadCSV::init(
const QString &base, 
const HiCalConf &conf,
 
  220                     const DbProfile &profile) {
 
  222    _csvSpecs = ResolveKeys(base, conf, profile);
 
  227  void LoadCSV::addHistory(
const QString &element,
 
  228                           const QString &desc) {
 
  229    std::ostringstream mess;
 
  230    mess << element << 
"[" << desc << 
"]";
 
  231    _history.push_back(mess.str().c_str());
 
  234  void LoadCSV::getKeyList(
const QString &base,
 
  235                           std::vector<QString> &keys)
 const {
 
  237    keys.push_back(base);
 
  238    keys.push_back(base+
"IgnoreComments");
 
  239    keys.push_back(base+
"ColumnHeader");
 
  240    keys.push_back(base+
"ColumnName");
 
  241    keys.push_back(base+
"ColumnIndex");
 
  242    keys.push_back(base+
"RowHeader");
 
  243    keys.push_back(base+
"RowName");
 
  244    keys.push_back(base+
"RowIndex");
 
  245    keys.push_back(base+
"SkipLines");
 
  246    keys.push_back(base+
"Header");
 
  247    keys.push_back(base+
"Separator");
 
  251  DbProfile LoadCSV::ResolveKeys(
const QString &base, 
const HiCalConf &conf,
 
  252                                 const DbProfile &prof)
 const {
 
  253    vector<QString> keys;
 
  254    getKeyList(base, keys);
 
  255    DbProfile keyprof(
"LoadCSV");
 
  256    for (
unsigned int i = 0 ; i < keys.size() ; i++) {
 
  257      QString kvalue = ParsedKey(keys[i], conf, prof);
 
  258      if (!kvalue.isEmpty())  keyprof.add(keys[i], kvalue);
 
  263  QString LoadCSV::ParsedKey(
const QString &key, 
const HiCalConf &conf,
 
  264                        const DbProfile &prof)
 const {
 
  266    if (prof.exists(key)) {
 
  267      value = conf.resolve(prof(key), prof);
 
  272  QString LoadCSV::makeKey(
const QString &suffix)
 const {
 
  273    QString key = _base + suffix;
 
  277  QString LoadCSV::getValue(
const QString &suffix)
 const {
 
  278    QString key = makeKey(suffix);
 
  280    if (_csvSpecs.exists(key)) value = _csvSpecs(key);
 
  284  int LoadCSV::getAxisIndex(
const QString &name,
 
  285                            const CSVReader::CSVAxis &header)
 const {
 
  286    QString head = name.trimmed();
 
  287    for (
int i = 0 ; i < header.dim() ; i++) {
 
  288      if (head.toLower() == header[i].toLower().trimmed()) {
 
This is free and unencumbered software released into the public domain.
int toInt(const QString &string)
Global function to convert from a string to an integer.
TNT::Array2D< double > HiMatrix
2-D buffer
const double Null
Value for an Isis Null pixel.
T ConfKey(const DbProfile &conf, const QString &keyname, const T &defval, int index=0)
Find a keyword in a profile using default for non-existant keywords.
TNT::Array1D< double > HiVector
1-D Buffer
QString ToString(const T &value)
Helper function to convert values to strings.
double ToDouble(const T &value)
Helper function to convert values to doubles.
int ToInteger(const T &value)
Helper function to convert values to Integers.
bool IsEqual(const QString &v1, const QString &v2="TRUE")
Shortened string equality test.
Namespace for the standard library.