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()) {