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