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