changeset 1113:ed207f89aaef

Fix assignment of values to regions on import, in case where region model contains duplicate points
author Chris Cannam
date Fri, 03 Jul 2015 16:09:14 +0100
parents 1517d4c60e88
children e80abd659922 020277bfafcb def2db9c4ab0
files data/fileio/CSVFileReader.cpp data/model/SparseModel.h
diffstat 2 files changed, 55 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/data/fileio/CSVFileReader.cpp	Wed Jul 01 15:53:54 2015 +0100
+++ b/data/fileio/CSVFileReader.cpp	Fri Jul 03 16:09:14 2015 +0100
@@ -35,6 +35,8 @@
 #include <iostream>
 #include <map>
 
+using namespace std;
+
 CSVFileReader::CSVFileReader(QString path, CSVFormat format,
                              sv_samplerate_t mainModelSampleRate) :
     m_format(format),
@@ -201,7 +203,7 @@
     sv_frame_t startFrame = 0; // for calculation of dense model resolution
     bool firstEverValue = true;
 
-    std::map<QString, int> labelCountMap;
+    map<QString, int> labelCountMap;
     
     int valueColumns = 0;
     for (int i = 0; i < m_format.getColumnCount(); ++i) {
@@ -319,11 +321,12 @@
 
                 case CSVFormat::ColumnLabel:
                     label = s;
-                    ++labelCountMap[label];
                     break;
                 }
             }
 
+            ++labelCountMap[label];
+            
             if (haveEndTime) { // ... calculate duration now all cols read
                 if (endFrame > frameNo) {
                     duration = endFrame - frameNo;
@@ -413,38 +416,51 @@
             // assign values for regions based on label frequency; we
             // have this in our labelCountMap, sort of
 
-            std::map<int, std::map<QString, float> > countLabelValueMap;
-            for (std::map<QString, int>::iterator i = labelCountMap.begin();
+            map<int, map<QString, float> > countLabelValueMap;
+            for (map<QString, int>::iterator i = labelCountMap.begin();
                  i != labelCountMap.end(); ++i) {
-                countLabelValueMap[i->second][i->first] = 0.f;
+                countLabelValueMap[i->second][i->first] = -1.f;
             }
 
             float v = 0.f;
-            for (std::map<int, std::map<QString, float> >::iterator i =
+            for (map<int, map<QString, float> >::iterator i =
                      countLabelValueMap.end(); i != countLabelValueMap.begin(); ) {
                 --i;
-                for (std::map<QString, float>::iterator j = i->second.begin();
+                cerr << "count -> " << i->first << endl;
+                for (map<QString, float>::iterator j = i->second.begin();
                      j != i->second.end(); ++j) {
                     j->second = v;
+                    cerr << "label -> " << j->first << ", value " << v << endl;
                     v = v + 1.f;
                 }
             }
 
-            std::map<RegionModel::Point, RegionModel::Point,
+            map<RegionModel::Point, RegionModel::Point,
                 RegionModel::Point::Comparator> pointMap;
             for (RegionModel::PointList::const_iterator i =
                      model2a->getPoints().begin();
                  i != model2a->getPoints().end(); ++i) {
                 RegionModel::Point p(*i);
-                v = countLabelValueMap[labelCountMap[p.label]][p.label];
+                int count = labelCountMap[p.label];
+                v = countLabelValueMap[count][p.label];
+                cerr << "mapping from label \"" << p.label << "\" (count " << count << ") to value " << v << endl;
                 RegionModel::Point pp(p.frame, v, p.duration, p.label);
                 pointMap[p] = pp;
             }
 
-            for (std::map<RegionModel::Point, RegionModel::Point>::iterator i = 
+            for (map<RegionModel::Point, RegionModel::Point>::iterator i = 
                      pointMap.begin(); i != pointMap.end(); ++i) {
-                model2a->deletePoint(i->first);
-                model2a->addPoint(i->second);
+                // There could be duplicate regions; if so replace
+                // them all -- but we need to check we're not
+                // replacing a region by itself (or else this will
+                // never terminate)
+                if (i->first.value == i->second.value) {
+                    continue;
+                }
+                while (model2a->containsPoint(i->first)) {
+                    model2a->deletePoint(i->first);
+                    model2a->addPoint(i->second);
+                }
             }
         }
     }
--- a/data/model/SparseModel.h	Wed Jul 01 15:53:54 2015 +0100
+++ b/data/model/SparseModel.h	Fri Jul 03 16:09:14 2015 +0100
@@ -133,6 +133,12 @@
      */
     virtual void deletePoint(const PointType &point);
 
+    /**
+     * Return true if the given point is found in this model, false
+     * otherwise.
+     */
+    virtual bool containsPoint(const PointType &point);
+    
     virtual bool isReady(int *completion = 0) const {
         bool ready = isOK() && (m_completion == 100);
         if (completion) *completion = m_completion;
@@ -774,6 +780,27 @@
 }
 
 template <typename PointType>
+bool
+SparseModel<PointType>::containsPoint(const PointType &point)
+{
+    {
+	QMutexLocker locker(&m_mutex);
+
+	PointListIterator i = m_points.lower_bound(point);
+	typename PointType::Comparator comparator;
+	while (i != m_points.end()) {
+	    if (i->frame > point.frame) break;
+	    if (!comparator(*i, point) && !comparator(point, *i)) {
+                return true;
+	    }
+	    ++i;
+	}
+    }
+
+    return false;
+}
+
+template <typename PointType>
 void
 SparseModel<PointType>::deletePoint(const PointType &point)
 {