39   LoadCSV::LoadCSV() : _base(), _csvSpecs(
"LoadCSV"), _data(0,0), _history() { }
    41   LoadCSV::LoadCSV(
const QString &base, 
const HiCalConf &conf,
    42                    const DbProfile &profile) : _base(), _csvSpecs(
"LoadCSV"),
    43                    _data(0,0), _history() {
    44     load(base, conf, profile);
    47   void LoadCSV::load(
const QString &base, 
const HiCalConf &conf,
    48                      const DbProfile &profile) {
    51     init(base, conf, profile);
    56     QString csvfile(conf.filepath(getValue()));
    57     addHistory(
"File", csvfile);
    61     bool colHeader(
IsEqual(
ConfKey(_csvSpecs,makeKey(
"Header"), QString(
"FALSE")), 
"TRUE"));
    62     bool rowHeader(colHeader);  
    63     if (
IsEqual(getValue(
"ColumnHeader"), 
"TRUE"))  colHeader = 
true;
    64     if (
IsEqual(getValue(
"RowHeader"), 
"TRUE"))  rowHeader = 
true;
    65     if (_csvSpecs.exists(makeKey(
"ColumnName"))) colHeader = 
true;
    66     if (_csvSpecs.exists(makeKey(
"RowName")   )) rowHeader = 
true;
    69     int skip = 
toInt(
ConfKey(_csvSpecs, makeKey(
"SkipLines"), QString(
"0")));
    70     addHistory(
"SkipLines", 
ToString(skip));
    71     bool comments = 
IsEqual(
ConfKey(_csvSpecs, makeKey(
"IgnoreComments"), QString(
"TRUE")));
    72     QString separator = 
ConfKey(_csvSpecs, makeKey(
"Separator"), QString(
","));
    73     if (separator.isEmpty()) separator = 
",";   
    76     csv.setComment(comments);
    78     csv.setHeader(colHeader);
    79     csv.setDelimiter(separator[0].toLatin1());
    80     if (separator[0] == 
' ') csv.setSkipEmptyParts();
    83     FileName csvF(csvfile);
    84     csvfile = csvF.expanded();
    87     } 
catch (IException &ie) {
    88       QString mess =  
"Could not read CSV file \'" + csvfile + 
"\'";
    89       throw IException(ie, IException::User, mess, 
_FILEINFO_);
    93     int ncols = csv.columns();
    94     int nrows = csv.rows();
    97     int startColumn((rowHeader) ? 1 : 0), endColumn(ncols-1);
    98     int startRow(0), endRow(nrows-1);
   101     QString colName(getValue(
"ColumnName"));
   102     if (!colName.isEmpty()) {
   103       addHistory(
"ColumnName", colName);
   104       CSVReader::CSVAxis chead = csv.getHeader();
   105       startColumn = getAxisIndex(colName, chead);
   106       if (startColumn < 0) {
   107         QString mess = 
"Column name " + colName +
   108                       " not found in CSV file " + csvfile;
   109         throw IException(IException::User, mess, 
_FILEINFO_);
   111       endColumn = startColumn;
   112       addHistory(
"ColumnIndex", 
ToString(startColumn));
   114     else if (!(getValue(
"ColumnIndex").isEmpty())) {
   115        startColumn = 
ToInteger(getValue(
"ColumnIndex")) +
   116                                  ((rowHeader) ? 1 : 0);
   117        endColumn = startColumn;
   118       addHistory(
"ColumnStart", 
ToString(startColumn));
   119       addHistory(
"ColumnEnd", 
ToString(endColumn));
   123     QString rowName(getValue(
"RowName"));
   124     if (!rowName.isEmpty()) {
   125       addHistory(
"RowName", rowName);
   127         QString mess = 
"Row name given but config does not specify presence of row header!";
   128         throw IException(IException::User, mess, 
_FILEINFO_);
   130       CSVReader::CSVAxis rhead = csv.getColumn(0);
   131       startRow = getAxisIndex(rowName, rhead);
   133         QString mess = 
"Row name " + rowName + 
" not found in CSV file " + csvfile;
   134         throw IException(IException::User, mess, 
_FILEINFO_);
   137       addHistory(
"RowIndex", 
ToString(startRow));
   139     else if (!(getValue(
"RowIndex").isEmpty())) {
   140        startRow = 
ToInteger(getValue(
"RowIndex"));
   141        if (rowHeader) startRow++;
   143       addHistory(
"RowStart", 
ToString(startRow));
   144       addHistory(
"RowEnd", 
ToString(endRow));
   148     int drows(endRow-startRow+1);
   149     int dcols(endColumn-startColumn+1);
   151     vector<QString> errors;
   152     for (
int r = startRow, hr = 0 ; r <= endRow ; r++, hr++) {
   153       CSVReader::CSVAxis row = csv.getRow(r);
   154       for (
int c = startColumn, hc = 0 ; c <= endColumn ; c++, hc++) {
   159           std::ostringstream mess;
   160           mess << 
"Invalid real value (" << row[c] << 
") in row index " << r;
   161           if (!rowName.isEmpty()) mess << 
" (Name:" << rowName << 
")";
   162           mess << 
", column index " << c;
   163           if (!colName.isEmpty()) mess << 
" (Name:" << colName << 
")";
   164           errors.push_back(mess.str().c_str());
   174     if (errors.size() > 0) {
   176       std::ostringstream mess;
   177       mess << 
"Conversion errors in CSV file " + csvfile + 
": Errors: ";
   179       std::vector<QString>::const_iterator it = errors.begin();
   181       while (it != errors.end()) {
   185       throw IException(IException::User, mess.str().c_str(), 
_FILEINFO_);
   191   QString LoadCSV::filename()
 const {
   195   int LoadCSV::size()
 const {
   196     return (_data.dim1() * _data.dim2());
   199   bool LoadCSV::validateSize(
const int &expected, 
const bool &throw_on_error)
   201     if (expected != size()) {
   202       if (!throw_on_error) 
return (
false);
   204       mess << 
"Invalid count (Expected: " << expected << 
", Received: "   205            << size() << 
") in CSV file " << getValue();
   206       throw IException(IException::User, mess.str(), 
_FILEINFO_);
   211   HiVector LoadCSV::getVector()
 const {
   212     HiVector v(size(), const_cast<double *> (_data[0]));
   216   HiMatrix LoadCSV::getMatrix()
 const {
   217     return (_data.copy());
   221   void LoadCSV::History(HiHistory &history)
 const {
   222     std::ostringstream mess;
   225     for (
unsigned int i = 0 ; i < _history.size() ; i++) {
   226       mess << comma << _history[i];
   230     history.add(mess.str().c_str());
   234   void LoadCSV::init(
const QString &base, 
const HiCalConf &conf,
   235                      const DbProfile &profile) {
   237     _csvSpecs = ResolveKeys(base, conf, profile);
   242   void LoadCSV::addHistory(
const QString &element,
   243                            const QString &desc) {
   244     std::ostringstream mess;
   245     mess << element << 
"[" << desc << 
"]";
   246     _history.push_back(mess.str().c_str());
   249   void LoadCSV::getKeyList(
const QString &base,
   250                            std::vector<QString> &keys)
 const {
   252     keys.push_back(base);
   253     keys.push_back(base+
"IgnoreComments");
   254     keys.push_back(base+
"ColumnHeader");
   255     keys.push_back(base+
"ColumnName");
   256     keys.push_back(base+
"ColumnIndex");
   257     keys.push_back(base+
"RowHeader");
   258     keys.push_back(base+
"RowName");
   259     keys.push_back(base+
"RowIndex");
   260     keys.push_back(base+
"SkipLines");
   261     keys.push_back(base+
"Header");
   262     keys.push_back(base+
"Separator");
   266   DbProfile LoadCSV::ResolveKeys(
const QString &base, 
const HiCalConf &conf,
   267                                  const DbProfile &prof)
 const {
   268     vector<QString> keys;
   269     getKeyList(base, keys);
   270     DbProfile keyprof(
"LoadCSV");
   271     for (
unsigned int i = 0 ; i < keys.size() ; i++) {
   272       QString kvalue = ParsedKey(keys[i], conf, prof);
   273       if (!kvalue.isEmpty())  keyprof.add(keys[i], kvalue);
   278   QString LoadCSV::ParsedKey(
const QString &key, 
const HiCalConf &conf,
   279                         const DbProfile &prof)
 const {
   281     if (prof.exists(key)) {
   282       value = conf.resolve(prof(key), prof);
   287   QString LoadCSV::makeKey(
const QString &suffix)
 const {
   288     QString key = _base + suffix;
   292   QString LoadCSV::getValue(
const QString &suffix)
 const {
   293     QString key = makeKey(suffix);
   295     if (_csvSpecs.exists(key)) value = _csvSpecs(key);
   299   int LoadCSV::getAxisIndex(
const QString &name,
   300                             const CSVReader::CSVAxis &header)
 const {
   301     QString head = name.trimmed();
   302     for (
int i = 0 ; i < header.dim() ; i++) {
   303       if (head.toLower() == header[i].toLower().trimmed()) {
 const double Null
Value for an Isis Null pixel. 
 
int toInt(const QString &string)
Global function to convert from a string to an integer. 
 
Namespace for the standard library. 
 
bool IsEqual(const QString &v1, const QString &v2="TRUE")
Shortened string equality test. 
 
int ToInteger(const T &value)
Helper function to convert values to Integers. 
 
#define _FILEINFO_
Macro for the filename and line number. 
 
double ToDouble(const T &value)
Helper function to convert values to doubles. 
 
Namespace for ISIS/Bullet specific routines. 
 
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. 
 
QString ToString(const T &value)
Helper function to convert values to strings. 
 
TNT::Array2D< double > HiMatrix
2-D buffer 
 
TNT::Array1D< double > HiVector
1-D Buffer