diff framework/SVFileReader.cpp @ 629:10046d544e76

Further work on #1773 "Loading a session with features extracted from multiplexed inputs". Re-read the aggregate wave models from the session file; also re-order the way they are written so as to improve the likelihood of successfully re-reading them (! - as it stood before, there was some chance involved)
author Chris Cannam
date Mon, 15 Oct 2018 15:50:39 +0100
parents 15a566f26114
children ca64cc9047d0
line wrap: on
line diff
--- a/framework/SVFileReader.cpp	Wed Oct 10 08:44:37 2018 +0100
+++ b/framework/SVFileReader.cpp	Mon Oct 15 15:50:39 2018 +0100
@@ -36,6 +36,7 @@
 #include "data/model/TextModel.h"
 #include "data/model/ImageModel.h"
 #include "data/model/AlignmentModel.h"
+#include "data/model/AggregateWaveModel.h"
 
 #include "transform/TransformFactory.h"
 
@@ -209,6 +210,7 @@
 
     } else if (name == "derivation") {
 
+        makeAggregateModels(); // must be done before derivations that use them
         ok = readDerivation(attributes);
 
     } else if (name == "playparameters") {
@@ -403,8 +405,60 @@
 }
 
 void
+SVFileReader::makeAggregateModels()
+{
+    std::map<int, PendingAggregateRec> stillPending;
+    
+    for (auto p: m_pendingAggregates) {
+
+        int id = p.first;
+        const PendingAggregateRec &rec = p.second;
+        bool skip = false;
+
+        AggregateWaveModel::ChannelSpecList specs;
+        for (int componentId: rec.components) {
+            bool found = false;
+            if (m_models.find(componentId) != m_models.end()) {
+                RangeSummarisableTimeValueModel *rs =
+                    dynamic_cast<RangeSummarisableTimeValueModel *>
+                    (m_models[componentId]);
+                if (rs) {
+                    specs.push_back(AggregateWaveModel::ModelChannelSpec
+                                    (rs, -1));
+                    found = true;
+                }
+            }
+            if (!found) {
+                SVDEBUG << "SVFileReader::makeAggregateModels:"
+                        << "Unknown component model id "
+                        << componentId << " in aggregate model id " << id
+                        << ", hoping we won't be needing it just yet"
+                        << endl;
+                skip = true;
+            }                
+        }
+
+        if (skip) {
+            stillPending[id] = rec;
+        } else {
+            AggregateWaveModel *model = new AggregateWaveModel(specs);
+            model->setObjectName(rec.name);
+
+            SVDEBUG << "SVFileReader::makeAggregateModels: created aggregate model id "
+                    << id << " with " << specs.size() << " components" << endl;
+        
+            m_models[id] = model;
+        }
+    }
+
+    m_pendingAggregates = stillPending;
+}
+
+void
 SVFileReader::addUnaddedModels()
 {
+    makeAggregateModels();
+    
     std::set<Model *> unaddedModels;
     
     for (std::map<int, Model *>::iterator i = m_models.begin();
@@ -510,6 +564,30 @@
 
         return true;
 
+    } else if (type == "aggregatewave") {
+
+        QString components = attributes.value("components");
+        QStringList componentIdStrings = components.split(",");
+        std::vector<int> componentIds;
+        for (auto cid: componentIdStrings) {
+            bool ok = false;
+            int id = cid.toInt(&ok);
+            if (!ok) {
+                SVCERR << "SVFileReader::readModel: Failed to convert component model id from part \"" << cid << "\" in \"" << components << "\"" << endl;
+            } else {
+                componentIds.push_back(id);
+            }
+        }
+        PendingAggregateRec rec { name, sampleRate, componentIds };
+        m_pendingAggregates[id] = rec;
+
+        // The aggregate model will be constructed from its pending
+        // record in makeAggregateModels; it can't happen here because
+        // the component models might not all have been observed yet
+        // (an unfortunate accident of the way the file is written)
+
+        return true;
+
     } else if (type == "dense") {
         
         READ_MANDATORY(int, dimensions, toInt);