diff data/fileio/CSVFileReader.cpp @ 628:001db550bd48

* Add option to import time+duration (or time+endtime) from CSV files (importing to Region layers) * Fix ffwd/rwd in Region layers so as to behave like time-value layers
author Chris Cannam
date Thu, 08 Jul 2010 14:22:28 +0000
parents dd97f7b3d120
children 3a5ee4b6c9ad
line wrap: on
line diff
--- a/data/fileio/CSVFileReader.cpp	Mon Jul 05 11:54:19 2010 +0000
+++ b/data/fileio/CSVFileReader.cpp	Thu Jul 08 14:22:28 2010 +0000
@@ -20,6 +20,7 @@
 #include "model/SparseOneDimensionalModel.h"
 #include "model/SparseTimeValueModel.h"
 #include "model/EditableDenseThreeDimensionalModel.h"
+#include "model/RegionModel.h"
 #include "DataFileReaderFactory.h"
 
 #include <QFile>
@@ -29,6 +30,7 @@
 #include <QTextStream>
 
 #include <iostream>
+#include <map>
 
 CSVFileReader::CSVFileReader(QString path, CSVFormat format,
                              size_t mainModelSampleRate) :
@@ -90,9 +92,10 @@
     }
 */
 
-    CSVFormat::ModelType   modelType = m_format.getModelType();
+    CSVFormat::ModelType modelType = m_format.getModelType();
     CSVFormat::TimingType timingType = m_format.getTimingType();
-    CSVFormat::TimeUnits   timeUnits = m_format.getTimeUnits();
+    CSVFormat::DurationType durationType = m_format.getDurationType();
+    CSVFormat::TimeUnits timeUnits = m_format.getTimeUnits();
     QString separator = m_format.getSeparator();
     QString::SplitBehavior behaviour = m_format.getSplitBehaviour();
     size_t sampleRate = m_format.getSampleRate();
@@ -114,6 +117,7 @@
 
     SparseOneDimensionalModel *model1 = 0;
     SparseTimeValueModel *model2 = 0;
+    RegionModel *model2a = 0;
     EditableDenseThreeDimensionalModel *model3 = 0;
     Model *model = 0;
 
@@ -126,8 +130,12 @@
     float min = 0.0, max = 0.0;
 
     size_t frameNo = 0;
+    size_t duration = 0;
     size_t startFrame = 0; // for calculation of dense model resolution
 
+    std::map<QString, float> labelValueMap;
+    float syntheticMax = 0.f;
+
     while (!in.atEnd()) {
 
         // QTextStream's readLine doesn't cope with old-style Mac
@@ -166,6 +174,11 @@
                     model = model2;
                     break;
 		
+                case CSVFormat::TwoDimensionalModelWithDuration:
+                    model2a = new RegionModel(sampleRate, windowSize, false);
+                    model = model2a;
+                    break;
+		
                 case CSVFormat::ThreeDimensionalModel:
                     model3 = new EditableDenseThreeDimensionalModel
                         (sampleRate,
@@ -180,6 +193,8 @@
             QStringList tidyList;
             QRegExp nonNumericRx("[^0-9eE.,+-]");
 
+            float value = 0.f;
+
             for (int i = 0; i < list.size(); ++i) {
 	    
                 QString s(list[i].trimmed());
@@ -190,41 +205,82 @@
                     s = s.mid(1, s.length() - 2);
                 }
 
-                if (i == 0 && timingType == CSVFormat::ExplicitTiming) {
+                if (timingType == CSVFormat::ExplicitTiming) {
 
+                    size_t calculatedFrame = 0;
+
+                    if (i == 0 ||
+                        (i == 1 &&
+                         modelType == CSVFormat::TwoDimensionalModelWithDuration)) {
+
+                        bool ok = false;
+                        QString numeric = s;
+                        numeric.remove(nonNumericRx);
+
+                        if (timeUnits == CSVFormat::TimeSeconds) {
+
+                            double time = numeric.toDouble(&ok);
+                            calculatedFrame = int(time * sampleRate + 0.5);
+
+                        } else {
+
+                            calculatedFrame = numeric.toInt(&ok);
+
+                            if (timeUnits == CSVFormat::TimeWindows) {
+                                calculatedFrame *= windowSize;
+                            }
+                        }
+			       
+                        if (!ok) {
+                            if (warnings < warnLimit) {
+                                std::cerr << "WARNING: CSVFileReader::load: "
+                                          << "Bad time format (\"" << s.toStdString()
+                                          << "\") in data line "
+                                          << lineno+1 << ":" << std::endl;
+                                std::cerr << line.toStdString() << std::endl;
+                            } else if (warnings == warnLimit) {
+                                std::cerr << "WARNING: Too many warnings" << std::endl;
+                            }
+                            ++warnings;
+                        }
+
+                        if (i == 0) frameNo = calculatedFrame;
+                        else {
+                            if (durationType == CSVFormat::EndTimes) {
+                                duration = calculatedFrame - frameNo;
+                            } else {
+                                duration = calculatedFrame;
+                            }
+                        }
+
+                        continue;
+                    }
+                }
+
+                if ((i == 1 &&
+                     modelType == CSVFormat::TwoDimensionalModel) ||
+                    (i == 2 &&
+                     modelType == CSVFormat::TwoDimensionalModelWithDuration)) {
                     bool ok = false;
-                    QString numeric = s;
-                    numeric.remove(nonNumericRx);
+                    value = s.toFloat(&ok);
+                    if (!ok) {
+                        // cf. RDFImporter::fillModel
+                        if (labelValueMap.find(s) == labelValueMap.end()) {
+                            syntheticMax = syntheticMax + 1.f;
+                            labelValueMap[s] = syntheticMax;
+                        }
+                        value = labelValueMap[s];
+                    } else {
+                        if (value > syntheticMax) syntheticMax = value;
+                    }
+                    if (i + 1 == list.size()) {
+                        // keep text around for use as label (none other given)
+                        tidyList.push_back(s);
+                    }
+                    continue;
+                }
 
-                    if (timeUnits == CSVFormat::TimeSeconds) {
-
-                        double time = numeric.toDouble(&ok);
-                        frameNo = int(time * sampleRate + 0.5);
-
-                    } else {
-
-                        frameNo = numeric.toInt(&ok);
-
-                        if (timeUnits == CSVFormat::TimeWindows) {
-                            frameNo *= windowSize;
-                        }
-                    }
-			       
-                    if (!ok) {
-                        if (warnings < warnLimit) {
-                            std::cerr << "WARNING: CSVFileReader::load: "
-                                      << "Bad time format (\"" << s.toStdString()
-                                      << "\") in data line "
-                                      << lineno+1 << ":" << std::endl;
-                            std::cerr << line.toStdString() << std::endl;
-                        } else if (warnings == warnLimit) {
-                            std::cerr << "WARNING: Too many warnings" << std::endl;
-                        }
-                        ++warnings;
-                    }
-                } else {
-                    tidyList.push_back(s);
-                }
+                tidyList.push_back(s);
             }
 
             if (modelType == CSVFormat::OneDimensionalModel) {
@@ -240,11 +296,21 @@
 
                 SparseTimeValueModel::Point point
                     (frameNo,
-                     tidyList.size() > 0 ? tidyList[0].toFloat() : 0.0,
-                     tidyList.size() > 1 ? tidyList[1] : QString("%1").arg(lineno+1));
+                     value,
+                     tidyList.size() > 0 ? tidyList[0] : QString("%1").arg(lineno+1));
 
                 model2->addPoint(point);
 
+            } else if (modelType == CSVFormat::TwoDimensionalModelWithDuration) {
+
+                RegionModel::Point point
+                    (frameNo,
+                     value,
+                     duration,
+                     tidyList.size() > 0 ? tidyList[0] : QString("%1").arg(lineno+1));
+
+                model2a->addPoint(point);
+
             } else if (modelType == CSVFormat::ThreeDimensionalModel) {
 
                 DenseThreeDimensionalModel::Column values;