changeset 507:0944d13689b2

* Implement proper RDF feature writing for track level features, using the feature attribute URI given in the plugin description RDF (if there is one)
author Chris Cannam
date Fri, 05 Dec 2008 14:19:04 +0000
parents 823e8a4feff5
children 1b8c748fd7ea
files rdf/PluginRDFDescription.cpp rdf/RDFFeatureWriter.cpp rdf/RDFFeatureWriter.h rdf/SimpleSPARQLQuery.cpp transform/FileFeatureWriter.cpp
diffstat 5 files changed, 102 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/rdf/PluginRDFDescription.cpp	Fri Dec 05 11:31:51 2008 +0000
+++ b/rdf/PluginRDFDescription.cpp	Fri Dec 05 14:19:04 2008 +0000
@@ -372,11 +372,14 @@
         }
 
         v = SimpleSPARQLQuery::singleResultQuery
-            (m, queryTemplate.arg("feature_attribute"), "feature_attribute");
+            (m, queryTemplate.arg("feature"), "feature");
 
         if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
+            cerr << "Feature attribute URI: \"" << v.value.toStdString() << "\"" << endl;
             m_outputFeatureAttributeURIMap[outputId] = v.value;
-        }
+        } else {
+            cerr << "No feature attribute URI: \"" << v.value.toStdString() << "\"" << endl;
+        }           
 
         v = SimpleSPARQLQuery::singleResultQuery
             (m, queryTemplate.arg("signal_type"), "signal_type");
--- a/rdf/RDFFeatureWriter.cpp	Fri Dec 05 11:31:51 2008 +0000
+++ b/rdf/RDFFeatureWriter.cpp	Fri Dec 05 14:19:04 2008 +0000
@@ -82,8 +82,6 @@
 RDFFeatureWriter::setTrackMetadata(QString trackId,
                                    TrackMetadata metadata)
 {
-    std::cerr << "RDFFeatureWriter::setTrackMetadata: \""
-              << trackId.toStdString() << "\" -> \"" << metadata.title.toStdString() << "\",\"" << metadata.maker.toStdString() << "\"" << std::endl;
     m_metadata[trackId] = metadata;
 }
 
@@ -165,6 +163,24 @@
         writeDenseRDF(stream, transform, output, features,
                       m_rdfDescriptions[pluginId], signalURI, timelineURI);
 
+    } else if (!m_plain &&
+               m_rdfDescriptions[pluginId].haveDescription() &&
+               m_rdfDescriptions[pluginId].getOutputDisposition
+               (output.identifier.c_str()) ==
+               PluginRDFDescription::OutputTrackLevel &&
+               m_rdfDescriptions[pluginId].getOutputFeatureAttributeURI
+               (output.identifier.c_str()) != "") {
+
+        QString signalURI = m_trackSignalURIs[trackId];
+
+        if (signalURI == "") {
+            cerr << "RDFFeatureWriter: INTERNAL ERROR: writing track-level features without having established a signal URI!" << endl;
+            exit(1);
+        }
+
+        writeTrackLevelRDF(stream, transform, output, features,
+                           m_rdfDescriptions[pluginId], signalURI);
+
     } else {
 
         writeSparseRDF(stream, transform, output, features,
@@ -249,7 +265,7 @@
             stream << "    dc:title \"\"\"" << tm.title << "\"\"\" ;\n";
         }
         if (tm.maker != "") {
-            stream << "    dc:creator [ a mo:MusicArtist; foaf:name \"\"\"" << tm.maker << "\"\"\" ] ;\n";
+            stream << "    foaf:maker [ a mo:MusicArtist; foaf:name \"\"\"" << tm.maker << "\"\"\" ] ;\n";
         }
     }
 
@@ -268,11 +284,14 @@
     QString outputId = od.identifier.c_str();
     QTextStream &stream = *sptr;
 
+    // There is no "needFeatureType" for track-level outputs, because
+    // we can't meaningfully write a feature at all if we don't know
+    // what property to use for it.  If the output is track level but
+    // there is no feature type given, we have to revert to events.
+
     bool needEventType = false;
     bool needSignalType = false;
 
-    //!!! feature attribute type is not yet supported
-
     //!!! bin names, extents and so on can be written out using e.g. vamp:bin_names ( "a" "b" "c" ) 
 
     if (desc.getOutputDisposition(outputId) == 
@@ -290,6 +309,26 @@
             needSignalType = true;
         }
 
+    } else if (desc.getOutputDisposition(outputId) ==
+               PluginRDFDescription::OutputTrackLevel) {
+
+        // see note above -- need to generate an event type if no
+        // feature type given, or if in plain mode
+
+        cerr << "Note: track level output" << endl;
+
+        if (m_plain) {
+        
+            needEventType = true;
+
+        } else if (desc.getOutputFeatureAttributeURI(outputId) == "") {
+    
+            if (desc.getOutputEventTypeURI(outputId) == "") {
+
+                needEventType = true;
+            }
+        }
+
     } else {
 
         // may need event type but won't need signal type
@@ -443,6 +482,46 @@
 }
 
 void
+RDFFeatureWriter::writeTrackLevelRDF(QTextStream *sptr,
+                                     const Transform &transform,
+                                     const Plugin::OutputDescriptor& od,
+                                     const Plugin::FeatureList& featureList,
+                                     PluginRDFDescription &desc,
+                                     QString signalURI)
+{
+    if (featureList.empty()) return;
+    QTextStream &stream = *sptr;
+        
+    bool plain = (m_plain || !desc.haveDescription());
+
+    QString outputId = od.identifier.c_str();
+    QString featureUri = desc.getOutputFeatureAttributeURI(outputId);
+
+    if (featureUri == "") {
+        cerr << "RDFFeatureWriter::writeTrackLevelRDF: ERROR: No feature URI available -- this function should not have been called!" << endl;
+        return;
+    }
+
+    for (int i = 0; i < featureList.size(); ++i) {
+
+        const Plugin::Feature &feature = featureList[i];
+
+        if (feature.values.empty()) {
+
+            if (feature.label == "") continue;
+
+            stream << signalURI << " " << featureUri << " \""
+                   << feature.label.c_str() << "\" .\n";
+
+        } else {
+
+            stream << signalURI << " " << featureUri << " \""
+                   << feature.values[0] << "\"^^xsd:float .\n";
+        }
+    }
+}
+
+void
 RDFFeatureWriter::writeDenseRDF(QTextStream *sptr,
                                 const Transform &transform,
                                 const Plugin::OutputDescriptor& od,
--- a/rdf/RDFFeatureWriter.h	Fri Dec 05 11:31:51 2008 +0000
+++ b/rdf/RDFFeatureWriter.h	Fri Dec 05 14:19:04 2008 +0000
@@ -78,6 +78,13 @@
                         PluginRDFDescription &desc,
                         QString timelineURI);
 
+    void writeTrackLevelRDF(QTextStream *stream,
+                            const Transform &transform,
+                            const Vamp::Plugin::OutputDescriptor &output,
+                            const Vamp::Plugin::FeatureList &features,
+                            PluginRDFDescription &desc,
+                            QString signalURI);
+
     void writeDenseRDF(QTextStream *stream,
                        const Transform &transform,
                        const Vamp::Plugin::OutputDescriptor &output,
--- a/rdf/SimpleSPARQLQuery.cpp	Fri Dec 05 11:31:51 2008 +0000
+++ b/rdf/SimpleSPARQLQuery.cpp	Fri Dec 05 14:19:04 2008 +0000
@@ -213,8 +213,10 @@
         errorString = "Failed to initialise Redland parser";
         return false;
     }
-    
+
+#ifdef DEBUG_SIMPLE_SPARQL_QUERY    
     std::cerr << "About to parse \"" << uri.toStdString() << "\"" << std::endl;
+#endif
     
     Profiler p("SimpleSPARQLQuery: Parse URI into LIBRDF model");
     
--- a/transform/FileFeatureWriter.cpp	Fri Dec 05 11:31:51 2008 +0000
+++ b/transform/FileFeatureWriter.cpp	Fri Dec 05 14:19:04 2008 +0000
@@ -171,8 +171,9 @@
     QString infilename = url.toLocalFile();
     if (infilename == "") infilename = url.path();
     basename = QFileInfo(infilename).baseName();
-//    cerr << "url = " << url.toString().toStdString() << ", infilename = "
-//         << infilename.toStdString() << ", basename = " << basename.toStdString() << endl;
+
+    cerr << "trackId = " << trackId.toStdString() << ", url = " << url.toString().toStdString() << ", infilename = "
+         << infilename.toStdString() << ", basename = " << basename.toStdString() << endl;
 
 
     if (m_baseDir != "") dirname = QFileInfo(m_baseDir).absoluteFilePath();