41 #include <dataquay/BasicStore.h> 42 #include <dataquay/PropertyObject.h> 46 using Dataquay::Nodes;
47 using Dataquay::Triple;
48 using Dataquay::Triples;
49 using Dataquay::BasicStore;
50 using Dataquay::PropertyObject;
67 Uri
expand(QString s) {
return m_store->expand(s); }
84 int &hopSize,
int &width,
int &height);
87 bool, std::vector<float> &, QString);
93 return "*.rdf *.n3 *.ttl";
131 m_store(new BasicStore),
133 m_sampleRate(sampleRate)
137 m_store->addPrefix(
"mo", Uri(
"http://purl.org/ontology/mo/"));
138 m_store->addPrefix(
"af", Uri(
"http://purl.org/ontology/af/"));
139 m_store->addPrefix(
"dc", Uri(
"http://purl.org/dc/elements/1.1/"));
140 m_store->addPrefix(
"tl", Uri(
"http://purl.org/NET/c4dm/timeline.owl#"));
141 m_store->addPrefix(
"event", Uri(
"http://purl.org/NET/c4dm/event.owl#"));
142 m_store->addPrefix(
"rdfs", Uri(
"http://www.w3.org/2000/01/rdf-schema#"));
146 if (uri.startsWith(
"file:")) {
149 url = QUrl::fromLocalFile(uri);
151 m_store->import(url, BasicStore::ImportIgnoreDuplicates);
152 }
catch (std::exception &e) {
177 std::vector<ModelId> models;
182 m_errorString = QString(
"Invalid audio data model (is audio file format supported?)");
215 (Triple(Node(), Uri(
"a"),
expand(
"mo:Signal"))).subjects();
217 foreach (Node sig, sigs) {
219 Node file =
m_store->complete(Triple(Node(),
expand(
"mo:encodes"), sig));
220 if (file == Node()) {
221 file =
m_store->complete(Triple(sig,
expand(
"mo:available_as"), Node()));
223 if (file == Node()) {
224 cerr <<
"RDFImporterImpl::getDataModelsAudio: ERROR: No source for signal " << sig << endl;
228 QString signal = sig.value;
229 QString source = file.value;
231 SVDEBUG <<
"NOTE: Seeking signal source \"" << source
236 SVDEBUG <<
"NOTE: Source is available: Local filename is \"" 243 m_errorString = QString(
"Signal source \"%1\" is not available").arg(source);
249 SVDEBUG <<
"NOTE: Signal source \"" << source
250 <<
"\" is not available, using file finder..." << endl;
257 cerr <<
"File finder returns: \"" << path
263 m_errorString = QString(
"Signal source \"%1\" is not available").arg(source);
272 reporter->
setMessage(RDFImporter::tr(
"Importing audio referenced in RDF..."));
275 auto newModel = std::make_shared<ReadOnlyWaveFileModel>
277 if (newModel->isOK()) {
278 cerr <<
"Successfully created wave file model from source at \"" << source <<
"\"" << endl;
280 models.push_back(modelId);
286 m_errorString = QString(
"Failed to create wave file model from source at \"%1\"").arg(source);
297 reporter->
setMessage(RDFImporter::tr(
"Importing dense signal data from RDF..."));
300 Nodes sigFeatures =
m_store->match
301 (Triple(Node(),
expand(
"af:signal_feature"), Node())).objects();
303 foreach (Node sf, sigFeatures) {
305 if (sf.type != Node::URI && sf.type != Node::Blank)
continue;
308 Node v =
m_store->complete(Triple(sf,
expand(
"af:value"), Node()));
310 QString feature = sf.value;
311 QString type = t.value;
312 QString value = v.value;
314 if (type ==
"" || value ==
"")
continue;
317 int windowLength = 0;
322 (feature, sampleRate, windowLength, hopSize, width, height);
325 cerr <<
"WARNING: Sample rate in dense feature description does not match our underlying rate -- using rate from feature description" << endl;
330 cerr <<
"WARNING: Dense feature description does not specify a hop size -- assuming 1" << endl;
335 cerr <<
"WARNING: Dense feature description does not specify feature signal dimensions -- assuming one-dimensional (height = 1)" << endl;
339 QStringList values = value.split(
' ', QString::SkipEmptyParts);
341 if (values.empty()) {
342 cerr <<
"WARNING: Dense feature description does not specify any values!" << endl;
348 auto m = std::make_shared<SparseTimeValueModel>
349 (sampleRate, hopSize,
false);
351 for (
int j = 0; j < values.size(); ++j) {
352 float f = values[j].toFloat();
353 Event e(j * hopSize, f,
"");
358 m->setRDFTypeURI(type);
363 auto m = std::make_shared<EditableDenseThreeDimensionalModel>
364 (sampleRate, hopSize, height,
false);
370 for (
int j = 0; j < values.size(); ++j) {
371 if (j % height == 0 && !column.empty()) {
372 m->setColumn(x++, column);
375 column.push_back(values[j].toFloat());
378 if (!column.empty()) {
379 m->setColumn(x++, column);
383 m->setRDFTypeURI(type);
391 QString featureTypeUri)
394 (Triple(Uri(featureUri),
expand(
"dc:title"), Node()));
396 if (n.type == Node::Literal && n.value !=
"") {
397 SVDEBUG <<
"RDFImporterImpl::getDenseModelTitle: Title (from signal) \"" << n.value <<
"\"" << endl;
402 (Triple(Uri(featureTypeUri),
expand(
"dc:title"), Node()));
404 if (n.type == Node::Literal && n.value !=
"") {
405 SVDEBUG <<
"RDFImporterImpl::getDenseModelTitle: Title (from signal type) \"" << n.value <<
"\"" << endl;
409 SVDEBUG <<
"RDFImporterImpl::getDenseModelTitle: No title available for feature <" << featureUri <<
">" << endl;
416 int &hopSize,
int &width,
int &height)
419 (Triple(Uri(featureUri),
expand(
"af:dimensions"), Node()));
421 cerr <<
"Dimensions = \"" << dim.value <<
"\"" << endl;
423 if (dim.type == Node::Literal && dim.value !=
"") {
424 QStringList dl = dim.value.split(
" ");
425 if (dl.empty()) dl.push_back(dim.value);
426 if (dl.size() > 0) height = dl[0].toInt();
427 if (dl.size() > 1) width = dl[1].toInt();
440 Node interval =
m_store->complete(Triple(Uri(featureUri),
expand(
"mo:time"), Node()));
443 cerr <<
"RDFImporterImpl::getDenseFeatureProperties: Feature time node " 444 << interval <<
" is not a tl:Interval" << endl;
448 Node tl =
m_store->complete(Triple(interval,
expand(
"tl:onTimeLine"), Node()));
451 cerr <<
"RDFImporterImpl::getDenseFeatureProperties: Interval node " 452 << interval <<
" lacks tl:onTimeLine property" << endl;
456 Node map =
m_store->complete(Triple(Node(),
expand(
"tl:rangeTimeLine"), tl));
459 cerr <<
"RDFImporterImpl::getDenseFeatureProperties: No map for " 460 <<
"timeline node " << tl << endl;
463 PropertyObject po(
m_store,
"tl:", map);
465 if (po.hasProperty(
"sampleRate")) {
466 sampleRate = po.getProperty(
"sampleRate").toDouble();
468 if (po.hasProperty(
"hopSize")) {
469 hopSize = po.getProperty(
"hopSize").toInt();
471 if (po.hasProperty(
"windowLength")) {
472 windowLength = po.getProperty(
"windowLength").toInt();
475 cerr <<
"sr = " << sampleRate <<
", hop = " << hopSize <<
", win = " << windowLength << endl;
483 reporter->
setMessage(RDFImporter::tr(
"Importing event data from RDF..."));
505 (Triple(Node(),
expand(
"a"),
expand(
"mo:Signal"))).subjects();
509 std::map<QString, std::map<QString, std::map<int, std::map<bool, ModelId> > > >
512 foreach (Node sig, sigs) {
514 Node interval =
m_store->complete(Triple(sig,
expand(
"mo:time"), Node()));
515 if (interval == Node())
continue;
517 Node tl =
m_store->complete(Triple(interval,
expand(
"tl:onTimeLine"), Node()));
518 if (tl == Node())
continue;
520 Nodes times =
m_store->match(Triple(Node(),
expand(
"tl:onTimeLine"), tl)).subjects();
522 foreach (Node tn, times) {
524 Nodes timedThings =
m_store->match(Triple(Node(),
expand(
"event:time"), tn)).subjects();
526 foreach (Node thing, timedThings) {
528 Node typ =
m_store->complete(Triple(thing,
expand(
"a"), Node()));
529 if (typ == Node())
continue;
531 Node valu =
m_store->complete(Triple(thing,
expand(
"af:feature"), Node()));
533 QString source = sig.value;
534 QString timeline = tl.value;
535 QString type = typ.value;
536 QString thinguri = thing.value;
561 bool text = (type.contains(
"Text") || type.contains(
"text"));
562 bool note = (type.contains(
"Note") || type.contains(
"note"));
565 label =
m_store->complete(Triple(thing,
expand(
"af:text"), Node())).value;
569 label =
m_store->complete(Triple(thing,
expand(
"rdfs:label"), Node())).value;
576 bool haveDuration =
false;
578 Node at =
m_store->complete(Triple(tn,
expand(
"tl:at"), Node()));
588 Node start =
m_store->complete(Triple(tn,
expand(
"tl:beginsAt"), Node()));
589 Node dur =
m_store->complete(Triple(tn,
expand(
"tl:duration"), Node()));
590 if (start != Node() && dur != Node()) {
592 (start.value.toStdString());
594 (dur.value.toStdString());
599 QString valuestring = valu.value;
600 std::vector<float> values;
602 if (valuestring !=
"") {
603 QStringList vsl = valuestring.split(
" ", QString::SkipEmptyParts);
604 for (
int j = 0; j < vsl.size(); ++j) {
605 bool success =
false;
606 float v = vsl[j].toFloat(&success);
607 if (success) values.push_back(v);
612 if (values.size() == 1) dimensions = 2;
613 else if (values.size() > 1) dimensions = 3;
617 if (modelMap[timeline][type][dimensions].find(haveDuration) ==
618 modelMap[timeline][type][dimensions].end()) {
627 Model *model =
nullptr;
631 if (dimensions == 1) {
637 }
else if (dimensions == 2) {
655 if (note || (dimensions > 2)) {
667 cerr <<
"source model for " << model <<
" is " <<
m_audioModelMap[source] << endl;
671 QString title =
m_store->complete
672 (Triple(typ,
expand(
"dc:title"), Node())).value;
676 title.replace(QRegExp(
"^.*[/#]"),
"");
678 model->setObjectName(title);
681 modelMap[timeline][type][dimensions][haveDuration] = modelId;
682 models.push_back(modelId);
685 modelId = modelMap[timeline][type][dimensions][haveDuration];
693 haveDuration, values, label);
705 std::vector<float> &values,
710 if (
auto sodm = ModelById::getAs<SparseOneDimensionalModel>(modelId)) {
711 Event point(ftime, label);
716 if (
auto tm = ModelById::getAs<TextModel>(modelId)) {
719 values.empty() ? 0.5f : values[0] < 0.f ? 0.f : values[0] > 1.f ? 1.f : values[0],
725 if (
auto stvm = ModelById::getAs<SparseTimeValueModel>(modelId)) {
726 Event e(ftime, values.empty() ? 0.f : values[0], label);
731 if (
auto nm = ModelById::getAs<NoteModel>(modelId)) {
733 float value = 0.f, level = 1.f;
734 if (!values.empty()) {
736 if (values.size() > 1) {
740 Event e(ftime, value, fduration, level, label);
743 float value = 0.f, duration = 1.f, level = 1.f;
744 if (!values.empty()) {
746 if (values.size() > 1) {
747 duration = values[1];
748 if (values.size() > 2) {
760 if (
auto rm = ModelById::getAs<RegionModel>(modelId)) {
762 if (values.empty()) {
772 Event e(ftime, value, fduration, label);
777 float duration = 1.f;
778 if (!values.empty()) {
780 if (values.size() > 1) {
781 duration = values[1];
790 cerr <<
"WARNING: RDFImporterImpl::fillModel: Unknown or unexpected model type" << endl;
797 bool haveAudio =
false;
798 bool haveAnnotations =
false;
799 bool haveRDF =
false;
801 if (!isPlausibleDocumentOfAnyKind(url)) {
805 BasicStore *store =
nullptr;
810 store = BasicStore::load(url);
811 Triple t = store->matchOnce(Triple());
812 if (t != Triple()) haveRDF =
true;
813 }
catch (std::exception &) {
822 store->addPrefix(
"mo", Uri(
"http://purl.org/ontology/mo/"));
823 store->addPrefix(
"event", Uri(
"http://purl.org/NET/c4dm/event.owl#"));
824 store->addPrefix(
"af", Uri(
"http://purl.org/ontology/af/"));
828 Node n = store->complete(Triple(Node(), Uri(
"a"), store->expand(
"mo:AudioFile")));
829 if (n != Node() && n.type == Node::URI) {
839 Nodes sigs = store->match(Triple(Node(), Uri(
"a"), store->expand(
"mo:Signal"))).subjects();
840 foreach (Node sig, sigs) {
841 Node aa = store->complete(Triple(sig, store->expand(
"mo:available_as"), Node()));
849 SVDEBUG <<
"NOTE: RDFImporter::identifyDocumentType: haveAudio = " 850 << haveAudio << endl;
853 n = store->matchOnce(Triple(Node(), store->expand(
"event:time"), Node())).c;
855 haveAnnotations =
true;
858 if (!haveAnnotations) {
860 n = store->matchOnce(Triple(Node(), store->expand(
"af:signal_feature"), Node())).c;
862 haveAnnotations =
true;
866 SVDEBUG <<
"NOTE: RDFImporter::identifyDocumentType: haveAnnotations = " 867 << haveAnnotations << endl;
872 if (haveAnnotations) {
873 return AudioRefAndAnnotations;
878 if (haveAnnotations) {
881 return OtherRDFDocument;
885 return OtherRDFDocument;
double sv_samplerate_t
Sample rate.
void getDataModelsSparse(std::vector< ModelId > &, ProgressReporter *)
std::map< QString, ModelId > m_audioModelMap
int64_t sv_frame_t
Frame index, the unit of our time axis.
QString getLocation() const
Return the location filename or URL as passed to the constructor.
QString getErrorString() const
static FileFinder * getInstance()
static QString getKnownExtensions()
Return the file extensions that we have data file readers for, in a format suitable for use with QFil...
QString getErrorString() const
void setRDFTypeURI(QString uri)
Set the event, feature, or signal type URI for the features contained in this model, according to the Audio Features RDF ontology.
static bool isPlausibleDocumentOfAnyKind(QUrl url)
QString getLocalFilename() const
Return the name of the local file this FileSource refers to.
void setSampleRate(sv_samplerate_t sampleRate)
A model representing casual textual annotations.
RDFImporterImpl(QString url, sv_samplerate_t sampleRate)
void waitForData()
Block on a sub-event-loop until the whole of the data has been retrieved (if it is remote)...
static Id add(std::shared_ptr< Item > item)
std::vector< ModelId > getDataModels(ProgressReporter *reporter)
Return a list of models imported from the RDF source.
void fillModel(ModelId, sv_frame_t, sv_frame_t, bool, std::vector< float > &, QString)
std::map< ModelId, std::map< QString, float > > m_labelValueMap
void setSampleRate(sv_samplerate_t sampleRate)
void getDataModelsAudio(std::vector< ModelId > &, ProgressReporter *)
Model is the base class for all data models that represent any sort of data on a time scale based on ...
RDFImporter(QString url, sv_samplerate_t sampleRate=0)
void getDenseFeatureProperties(QString featureUri, sv_samplerate_t &sampleRate, int &windowLength, int &hopSize, int &width, int &height)
static bool isApparentTextDocument(FileSource)
Return true if the source appears to point to a text format of some kind (could be CSV...
FileSource is a class used to refer to the contents of a file that may be either local or at a remote...
static sv_frame_t realTime2Frame(const RealTime &r, sv_samplerate_t sampleRate)
Convert a RealTime into a sample frame at the given sample rate.
virtual void setSourceModel(ModelId model)
Set the source model for this model.
void getDataModelsDense(std::vector< ModelId > &, ProgressReporter *)
A model representing a wiggly-line plot with points at arbitrary intervals of the model resolution...
RegionModel – a model for intervals associated with a value, which we call regions for no very compe...
An immutable(-ish) type used for point and event representation in sparse models, as well as for inte...
static RDFDocumentType identifyDocumentType(QUrl url)
virtual ~RDFImporterImpl()
virtual QString find(FileType type, QString location, QString lastKnownLocation="")=0
virtual void setMessage(QString text)=0
A model representing a series of time instants with optional labels but without values.
static RealTime fromXsdDuration(std::string xsdd)
QString getDenseModelTitle(QString featureUri, QString featureTypeUri)
std::vector< ModelId > getDataModels(ProgressReporter *)
sv_samplerate_t m_sampleRate
RealTime represents time values to nanosecond precision with accurate arithmetic and frame-rate conve...
bool isAvailable()
Return true if the file or remote URL exists.