svcore  1.9
RDFImporter.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7  This file copyright 2008-2012 QMUL.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #include "RDFImporter.h"
17 
18 #include <map>
19 #include <vector>
20 
21 #include <iostream>
22 #include <cmath>
23 
24 #include "base/ProgressReporter.h"
25 #include "base/RealTime.h"
26 
30 #include "data/model/NoteModel.h"
31 #include "data/model/TextModel.h"
32 #include "data/model/RegionModel.h"
34 
35 #include "data/fileio/FileSource.h"
36 #include "data/fileio/CachedFile.h"
37 #include "data/fileio/FileFinder.h"
38 
39 #include <dataquay/BasicStore.h>
40 #include <dataquay/PropertyObject.h>
41 
42 using Dataquay::Uri;
43 using Dataquay::Node;
44 using Dataquay::Nodes;
45 using Dataquay::Triple;
46 using Dataquay::Triples;
47 using Dataquay::BasicStore;
48 using Dataquay::PropertyObject;
49 
51 {
52 public:
53  RDFImporterImpl(QString url, int sampleRate);
54  virtual ~RDFImporterImpl();
55 
56  void setSampleRate(int sampleRate) { m_sampleRate = sampleRate; }
57 
58  bool isOK();
59  QString getErrorString() const;
60 
61  std::vector<Model *> getDataModels(ProgressReporter *);
62 
63 protected:
64  BasicStore *m_store;
65  Uri expand(QString s) { return m_store->expand(s); }
66 
67  QString m_uristring;
68  QString m_errorString;
69  std::map<QString, Model *> m_audioModelMap;
71 
72  std::map<Model *, std::map<QString, float> > m_labelValueMap;
73 
74  void getDataModelsAudio(std::vector<Model *> &, ProgressReporter *);
75  void getDataModelsSparse(std::vector<Model *> &, ProgressReporter *);
76  void getDataModelsDense(std::vector<Model *> &, ProgressReporter *);
77 
78  void getDenseModelTitle(Model *, QString, QString);
79 
80  void getDenseFeatureProperties(QString featureUri,
81  int &sampleRate, int &windowLength,
82  int &hopSize, int &width, int &height);
83 
84  void fillModel(Model *, long, long, bool, std::vector<float> &, QString);
85 };
86 
87 QString
89 {
90  return "*.rdf *.n3 *.ttl";
91 }
92 
93 RDFImporter::RDFImporter(QString url, int sampleRate) :
94  m_d(new RDFImporterImpl(url, sampleRate))
95 {
96 }
97 
99 {
100  delete m_d;
101 }
102 
103 void
105 {
106  m_d->setSampleRate(sampleRate);
107 }
108 
109 bool
111 {
112  return m_d->isOK();
113 }
114 
115 QString
117 {
118  return m_d->getErrorString();
119 }
120 
121 std::vector<Model *>
123 {
124  return m_d->getDataModels(r);
125 }
126 
127 RDFImporterImpl::RDFImporterImpl(QString uri, int sampleRate) :
128  m_store(new BasicStore),
129  m_uristring(uri),
130  m_sampleRate(sampleRate)
131 {
133 
134  m_store->addPrefix("mo", Uri("http://purl.org/ontology/mo/"));
135  m_store->addPrefix("af", Uri("http://purl.org/ontology/af/"));
136  m_store->addPrefix("dc", Uri("http://purl.org/dc/elements/1.1/"));
137  m_store->addPrefix("tl", Uri("http://purl.org/NET/c4dm/timeline.owl#"));
138  m_store->addPrefix("event", Uri("http://purl.org/NET/c4dm/event.owl#"));
139  m_store->addPrefix("rdfs", Uri("http://www.w3.org/2000/01/rdf-schema#"));
140 
141  try {
142  QUrl url;
143  if (uri.startsWith("file:")) {
144  url = QUrl(uri);
145  } else {
146  url = QUrl::fromLocalFile(uri);
147  }
148  m_store->import(url, BasicStore::ImportIgnoreDuplicates);
149  } catch (std::exception &e) {
150  m_errorString = e.what();
151  }
152 }
153 
155 {
156  delete m_store;
157 }
158 
159 bool
161 {
162  return (m_errorString == "");
163 }
164 
165 QString
167 {
168  return m_errorString;
169 }
170 
171 std::vector<Model *>
173 {
174  std::vector<Model *> models;
175 
176  getDataModelsAudio(models, reporter);
177 
178  if (m_sampleRate == 0) {
179  m_errorString = QString("Invalid audio data model (is audio file format supported?)");
180  cerr << m_errorString << endl;
181  return models;
182  }
183 
184  QString error;
185 
186  if (m_errorString != "") {
187  error = m_errorString;
188  }
189  m_errorString = "";
190 
191  getDataModelsDense(models, reporter);
192 
193  if (m_errorString != "") {
194  error = m_errorString;
195  }
196  m_errorString = "";
197 
198  getDataModelsSparse(models, reporter);
199 
200  if (m_errorString == "" && error != "") {
201  m_errorString = error;
202  }
203 
204  return models;
205 }
206 
207 void
208 RDFImporterImpl::getDataModelsAudio(std::vector<Model *> &models,
209  ProgressReporter *reporter)
210 {
211  Nodes sigs = m_store->match
212  (Triple(Node(), Uri("a"), expand("mo:Signal"))).subjects();
213 
214  foreach (Node sig, sigs) {
215 
216  Node file = m_store->complete(Triple(Node(), expand("mo:encodes"), sig));
217  if (file == Node()) {
218  file = m_store->complete(Triple(sig, expand("mo:available_as"), Node()));
219  }
220  if (file == Node()) {
221  cerr << "RDFImporterImpl::getDataModelsAudio: ERROR: No source for signal " << sig << endl;
222  continue;
223  }
224 
225  QString signal = sig.value;
226  QString source = file.value;
227 
228  SVDEBUG << "NOTE: Seeking signal source \"" << source
229  << "\"..." << endl;
230 
231  FileSource *fs = new FileSource(source, reporter);
232  if (fs->isAvailable()) {
233  SVDEBUG << "NOTE: Source is available: Local filename is \""
234  << fs->getLocalFilename()
235  << "\"..." << endl;
236  }
237 
238 #ifdef NO_SV_GUI
239  if (!fs->isAvailable()) {
240  m_errorString = QString("Signal source \"%1\" is not available").arg(source);
241  delete fs;
242  continue;
243  }
244 #else
245  if (!fs->isAvailable()) {
246  SVDEBUG << "NOTE: Signal source \"" << source
247  << "\" is not available, using file finder..." << endl;
249  if (ff) {
250  QString path = ff->find(FileFinder::AudioFile,
251  fs->getLocation(),
252  m_uristring);
253  if (path != "") {
254  cerr << "File finder returns: \"" << path
255  << "\"" << endl;
256  delete fs;
257  fs = new FileSource(path, reporter);
258  if (!fs->isAvailable()) {
259  delete fs;
260  m_errorString = QString("Signal source \"%1\" is not available").arg(source);
261  continue;
262  }
263  }
264  }
265  }
266 #endif
267 
268  if (reporter) {
269  reporter->setMessage(RDFImporter::tr("Importing audio referenced in RDF..."));
270  }
271  fs->waitForData();
272  WaveFileModel *newModel = new WaveFileModel(*fs, m_sampleRate);
273  if (newModel->isOK()) {
274  cerr << "Successfully created wave file model from source at \"" << source << "\"" << endl;
275  models.push_back(newModel);
276  m_audioModelMap[signal] = newModel;
277  if (m_sampleRate == 0) {
278  m_sampleRate = newModel->getSampleRate();
279  }
280  } else {
281  m_errorString = QString("Failed to create wave file model from source at \"%1\"").arg(source);
282  delete newModel;
283  }
284  delete fs;
285  }
286 }
287 
288 void
289 RDFImporterImpl::getDataModelsDense(std::vector<Model *> &models,
290  ProgressReporter *reporter)
291 {
292  if (reporter) {
293  reporter->setMessage(RDFImporter::tr("Importing dense signal data from RDF..."));
294  }
295 
296  Nodes sigFeatures = m_store->match
297  (Triple(Node(), expand("af:signal_feature"), Node())).objects();
298 
299  foreach (Node sf, sigFeatures) {
300 
301  if (sf.type != Node::URI && sf.type != Node::Blank) continue;
302 
303  Node t = m_store->complete(Triple(sf, expand("a"), Node()));
304  Node v = m_store->complete(Triple(sf, expand("af:value"), Node()));
305 
306  QString feature = sf.value;
307  QString type = t.value;
308  QString value = v.value;
309 
310  if (type == "" || value == "") continue;
311 
312  int sampleRate = 0;
313  int windowLength = 0;
314  int hopSize = 0;
315  int width = 0;
316  int height = 0;
318  (feature, sampleRate, windowLength, hopSize, width, height);
319 
320  if (sampleRate != 0 && sampleRate != m_sampleRate) {
321  cerr << "WARNING: Sample rate in dense feature description does not match our underlying rate -- using rate from feature description" << endl;
322  }
323  if (sampleRate == 0) sampleRate = m_sampleRate;
324 
325  if (hopSize == 0) {
326  cerr << "WARNING: Dense feature description does not specify a hop size -- assuming 1" << endl;
327  hopSize = 1;
328  }
329 
330  if (height == 0) {
331  cerr << "WARNING: Dense feature description does not specify feature signal dimensions -- assuming one-dimensional (height = 1)" << endl;
332  height = 1;
333  }
334 
335  QStringList values = value.split(' ', QString::SkipEmptyParts);
336 
337  if (values.empty()) {
338  cerr << "WARNING: Dense feature description does not specify any values!" << endl;
339  continue;
340  }
341 
342  if (height == 1) {
343 
345  (sampleRate, hopSize, false);
346 
347  for (int j = 0; j < values.size(); ++j) {
348  float f = values[j].toFloat();
349  SparseTimeValueModel::Point point(j * hopSize, f, "");
350  m->addPoint(point);
351  }
352 
353  getDenseModelTitle(m, feature, type);
354 
355  m->setRDFTypeURI(type);
356 
357  models.push_back(m);
358 
359  } else {
360 
363  (sampleRate, hopSize, height,
365 
367 
368  int x = 0;
369 
370  for (int j = 0; j < values.size(); ++j) {
371  if (j % height == 0 && !column.empty()) {
372  m->setColumn(x++, column);
373  column.clear();
374  }
375  column.push_back(values[j].toFloat());
376  }
377 
378  if (!column.empty()) {
379  m->setColumn(x++, column);
380  }
381 
382  getDenseModelTitle(m, feature, type);
383 
384  m->setRDFTypeURI(type);
385 
386  models.push_back(m);
387  }
388  }
389 }
390 
391 void
393  QString featureUri,
394  QString featureTypeUri)
395 {
396  Node n = m_store->complete
397  (Triple(Uri(featureUri), expand("dc:title"), Node()));
398 
399  if (n.type == Node::Literal && n.value != "") {
400  SVDEBUG << "RDFImporterImpl::getDenseModelTitle: Title (from signal) \"" << n.value << "\"" << endl;
401  m->setObjectName(n.value);
402  return;
403  }
404 
405  n = m_store->complete
406  (Triple(Uri(featureTypeUri), expand("dc:title"), Node()));
407 
408  if (n.type == Node::Literal && n.value != "") {
409  SVDEBUG << "RDFImporterImpl::getDenseModelTitle: Title (from signal type) \"" << n.value << "\"" << endl;
410  m->setObjectName(n.value);
411  return;
412  }
413 
414  SVDEBUG << "RDFImporterImpl::getDenseModelTitle: No title available for feature <" << featureUri << ">" << endl;
415 }
416 
417 void
419  int &sampleRate, int &windowLength,
420  int &hopSize, int &width, int &height)
421 {
422  Node dim = m_store->complete
423  (Triple(Uri(featureUri), expand("af:dimensions"), Node()));
424 
425  cerr << "Dimensions = \"" << dim.value << "\"" << endl;
426 
427  if (dim.type == Node::Literal && dim.value != "") {
428  QStringList dl = dim.value.split(" ");
429  if (dl.empty()) dl.push_back(dim.value);
430  if (dl.size() > 0) height = dl[0].toInt();
431  if (dl.size() > 1) width = dl[1].toInt();
432  }
433 
434  // Looking for rate, hop, window from:
435  //
436  // ?feature mo:time ?time .
437  // ?time a tl:Interval .
438  // ?time tl:onTimeLine ?timeline .
439  // ?map tl:rangeTimeLine ?timeline .
440  // ?map tl:sampleRate ?rate .
441  // ?map tl:hopSize ?hop .
442  // ?map tl:windowLength ?window .
443 
444  Node interval = m_store->complete(Triple(Uri(featureUri), expand("mo:time"), Node()));
445 
446  if (!m_store->contains(Triple(interval, expand("a"), expand("tl:Interval")))) {
447  cerr << "RDFImporterImpl::getDenseFeatureProperties: Feature time node "
448  << interval << " is not a tl:Interval" << endl;
449  return;
450  }
451 
452  Node tl = m_store->complete(Triple(interval, expand("tl:onTimeLine"), Node()));
453 
454  if (tl == Node()) {
455  cerr << "RDFImporterImpl::getDenseFeatureProperties: Interval node "
456  << interval << " lacks tl:onTimeLine property" << endl;
457  return;
458  }
459 
460  Node map = m_store->complete(Triple(Node(), expand("tl:rangeTimeLine"), tl));
461 
462  if (map == Node()) {
463  cerr << "RDFImporterImpl::getDenseFeatureProperties: No map for "
464  << "timeline node " << tl << endl;
465  }
466 
467  PropertyObject po(m_store, "tl:", map);
468 
469  if (po.hasProperty("sampleRate")) {
470  sampleRate = po.getProperty("sampleRate").toInt();
471  }
472  if (po.hasProperty("hopSize")) {
473  hopSize = po.getProperty("hopSize").toInt();
474  }
475  if (po.hasProperty("windowLength")) {
476  windowLength = po.getProperty("windowLength").toInt();
477  }
478 
479  cerr << "sr = " << sampleRate << ", hop = " << hopSize << ", win = " << windowLength << endl;
480 }
481 
482 void
483 RDFImporterImpl::getDataModelsSparse(std::vector<Model *> &models,
484  ProgressReporter *reporter)
485 {
486  if (reporter) {
487  reporter->setMessage(RDFImporter::tr("Importing event data from RDF..."));
488  }
489 
490  /*
491  This function is only used for sparse data (for dense data we
492  would be in getDataModelsDense instead).
493 
494  Our query is intended to retrieve every thing that has a time,
495  and every feature type and value associated with a thing that
496  has a time.
497 
498  We will then need to refine this big bag of results into a set
499  of data models.
500 
501  Results that have different source signals should go into
502  different models.
503 
504  Results that have different feature types should go into
505  different models.
506  */
507 
508  Nodes sigs = m_store->match
509  (Triple(Node(), expand("a"), expand("mo:Signal"))).subjects();
510 
511  // Map from timeline uri to event type to dimensionality to
512  // presence of duration to model ptr. Whee!
513  std::map<QString, std::map<QString, std::map<int, std::map<bool, Model *> > > >
514  modelMap;
515 
516  foreach (Node sig, sigs) {
517 
518  Node interval = m_store->complete(Triple(sig, expand("mo:time"), Node()));
519  if (interval == Node()) continue;
520 
521  Node tl = m_store->complete(Triple(interval, expand("tl:onTimeLine"), Node()));
522  if (tl == Node()) continue;
523 
524  Nodes times = m_store->match(Triple(Node(), expand("tl:onTimeLine"), tl)).subjects();
525 
526  foreach (Node tn, times) {
527 
528  Nodes timedThings = m_store->match(Triple(Node(), expand("event:time"), tn)).subjects();
529 
530  foreach (Node thing, timedThings) {
531 
532  Node typ = m_store->complete(Triple(thing, expand("a"), Node()));
533  if (typ == Node()) continue;
534 
535  Node valu = m_store->complete(Triple(thing, expand("af:feature"), Node()));
536 
537  QString source = sig.value;
538  QString timeline = tl.value;
539  QString type = typ.value;
540  QString thinguri = thing.value;
541 
542  /*
543  For sparse data, the determining factors in deciding
544  what model to use are: Do the features have values?
545  and Do the features have duration?
546 
547  We can run through the results and check off whether
548  we find values and duration for each of the
549  source+type keys, and then run through the
550  source+type keys pushing each of the results into a
551  suitable model.
552 
553  Unfortunately, at this point we do not yet have any
554  actual timing data (time/duration) -- just the time
555  URI.
556 
557  What we _could_ do is to create one of each type of
558  model at the start, for each of the source+type
559  keys, and then push each feature into the relevant
560  model depending on what we find out about it. Then
561  return only non-empty models.
562  */
563 
564  QString label = "";
565  bool text = (type.contains("Text") || type.contains("text")); // Ha, ha
566  bool note = (type.contains("Note") || type.contains("note")); // Guffaw
567 
568  if (text) {
569  label = m_store->complete(Triple(thing, expand("af:text"), Node())).value;
570  }
571 
572  if (label == "") {
573  label = m_store->complete(Triple(thing, expand("rdfs:label"), Node())).value;
574  }
575 
576  RealTime time;
577  RealTime duration;
578 
579 // bool haveTime = false;
580  bool haveDuration = false;
581 
582  Node at = m_store->complete(Triple(tn, expand("tl:at"), Node()));
583 
584  if (at != Node()) {
585  time = RealTime::fromXsdDuration(at.value.toStdString());
586 // haveTime = true;
587  } else {
589  // beginsAt -> start
590  // onTimeLine -> timeline
591 
592  Node start = m_store->complete(Triple(tn, expand("tl:beginsAt"), Node()));
593  Node dur = m_store->complete(Triple(tn, expand("tl:duration"), Node()));
594  if (start != Node() && dur != Node()) {
596  (start.value.toStdString());
597  duration = RealTime::fromXsdDuration
598  (dur.value.toStdString());
599 // haveTime = haveDuration = true;
600  }
601  }
602 
603  QString valuestring = valu.value;
604  std::vector<float> values;
605 
606  if (valuestring != "") {
607  QStringList vsl = valuestring.split(" ", QString::SkipEmptyParts);
608  for (int j = 0; j < vsl.size(); ++j) {
609  bool success = false;
610  float v = vsl[j].toFloat(&success);
611  if (success) values.push_back(v);
612  }
613  }
614 
615  int dimensions = 1;
616  if (values.size() == 1) dimensions = 2;
617  else if (values.size() > 1) dimensions = 3;
618 
619  Model *model = 0;
620 
621  if (modelMap[timeline][type][dimensions].find(haveDuration) ==
622  modelMap[timeline][type][dimensions].end()) {
623 
624 /*
625  SVDEBUG << "Creating new model: source = " << source << ", type = " << type << ", dimensions = "
626  << dimensions << ", haveDuration = " << haveDuration
627  << ", time = " << time << ", duration = " << duration
628  << endl;
629 */
630 
631  if (!haveDuration) {
632 
633  if (dimensions == 1) {
634  if (text) {
635  model = new TextModel(m_sampleRate, 1, false);
636  } else {
637  model = new SparseOneDimensionalModel(m_sampleRate, 1, false);
638  }
639  } else if (dimensions == 2) {
640  if (text) {
641  model = new TextModel(m_sampleRate, 1, false);
642  } else {
643  model = new SparseTimeValueModel(m_sampleRate, 1, false);
644  }
645  } else {
646  // We don't have a three-dimensional sparse model,
647  // so use a note model. We do have some logic (in
648  // extractStructure below) for guessing whether
649  // this should after all have been a dense model,
650  // but it's hard to apply it because we don't have
651  // all the necessary timing data yet... hmm
652  model = new NoteModel(m_sampleRate, 1, false);
653  }
654 
655  } else { // haveDuration
656 
657  if (note || (dimensions > 2)) {
658  model = new NoteModel(m_sampleRate, 1, false);
659  } else {
660  // If our units are frequency or midi pitch, we
661  // should be using a note model... hm
662  model = new RegionModel(m_sampleRate, 1, false);
663  }
664  }
665 
666  model->setRDFTypeURI(type);
667 
668  if (m_audioModelMap.find(source) != m_audioModelMap.end()) {
669  cerr << "source model for " << model << " is " << m_audioModelMap[source] << endl;
670  model->setSourceModel(m_audioModelMap[source]);
671  }
672 
673  QString title = m_store->complete
674  (Triple(typ, expand("dc:title"), Node())).value;
675  if (title == "") {
676  // take it from the end of the event type
677  title = type;
678  title.replace(QRegExp("^.*[/#]"), "");
679  }
680  model->setObjectName(title);
681 
682  modelMap[timeline][type][dimensions][haveDuration] = model;
683  models.push_back(model);
684  }
685 
686  model = modelMap[timeline][type][dimensions][haveDuration];
687 
688  if (model) {
689  long ftime = RealTime::realTime2Frame(time, m_sampleRate);
690  long fduration = RealTime::realTime2Frame(duration, m_sampleRate);
691  fillModel(model, ftime, fduration, haveDuration, values, label);
692  }
693  }
694  }
695  }
696 }
697 
698 void
700  long ftime,
701  long fduration,
702  bool haveDuration,
703  std::vector<float> &values,
704  QString label)
705 {
706 // SVDEBUG << "RDFImporterImpl::fillModel: adding point at frame " << ftime << endl;
707 
709  dynamic_cast<SparseOneDimensionalModel *>(model);
710  if (sodm) {
711  SparseOneDimensionalModel::Point point(ftime, label);
712  sodm->addPoint(point);
713  return;
714  }
715 
716  TextModel *tm =
717  dynamic_cast<TextModel *>(model);
718  if (tm) {
719  TextModel::Point point
720  (ftime,
721  values.empty() ? 0.5f : values[0] < 0.f ? 0.f : values[0] > 1.f ? 1.f : values[0], // I was young and feckless once too
722  label);
723  tm->addPoint(point);
724  return;
725  }
726 
727  SparseTimeValueModel *stvm =
728  dynamic_cast<SparseTimeValueModel *>(model);
729  if (stvm) {
731  (ftime, values.empty() ? 0.f : values[0], label);
732  stvm->addPoint(point);
733  return;
734  }
735 
736  NoteModel *nm =
737  dynamic_cast<NoteModel *>(model);
738  if (nm) {
739  if (haveDuration) {
740  float value = 0.f, level = 1.f;
741  if (!values.empty()) {
742  value = values[0];
743  if (values.size() > 1) {
744  level = values[1];
745  }
746  }
747  NoteModel::Point point(ftime, value, fduration, level, label);
748  nm->addPoint(point);
749  } else {
750  float value = 0.f, duration = 1.f, level = 1.f;
751  if (!values.empty()) {
752  value = values[0];
753  if (values.size() > 1) {
754  duration = values[1];
755  if (values.size() > 2) {
756  level = values[2];
757  }
758  }
759  }
760  NoteModel::Point point(ftime, value, duration, level, label);
761  nm->addPoint(point);
762  }
763  return;
764  }
765 
766  RegionModel *rm =
767  dynamic_cast<RegionModel *>(model);
768  if (rm) {
769  float value = 0.f;
770  if (values.empty()) {
771  // no values? map each unique label to a distinct value
772  if (m_labelValueMap[model].find(label) == m_labelValueMap[model].end()) {
773  m_labelValueMap[model][label] = rm->getValueMaximum() + 1.f;
774  }
775  value = m_labelValueMap[model][label];
776  } else {
777  value = values[0];
778  }
779  if (haveDuration) {
780  RegionModel::Point point(ftime, value, fduration, label);
781  rm->addPoint(point);
782  } else {
783  // This won't actually happen -- we only create region models
784  // if we do have duration -- but just for completeness
785  float duration = 1.f;
786  if (!values.empty()) {
787  value = values[0];
788  if (values.size() > 1) {
789  duration = values[1];
790  }
791  }
792  RegionModel::Point point(ftime, value, duration, label);
793  rm->addPoint(point);
794  }
795  return;
796  }
797 
798  cerr << "WARNING: RDFImporterImpl::fillModel: Unknown or unexpected model type" << endl;
799  return;
800 }
801 
804 {
805  bool haveAudio = false;
806  bool haveAnnotations = false;
807  bool haveRDF = false;
808 
809  BasicStore *store = 0;
810 
811  // This is not expected to return anything useful, but if it does
812  // anything at all then we know we have RDF
813  try {
815  store = BasicStore::load(QUrl(url));
816  Triple t = store->matchOnce(Triple());
817  if (t != Triple()) haveRDF = true;
818  } catch (std::exception &e) {
819  // nothing; haveRDF will be false so the next bit catches it
820  }
821 
822  if (!haveRDF) {
823  delete store;
824  return NotRDF;
825  }
826 
827  store->addPrefix("mo", Uri("http://purl.org/ontology/mo/"));
828  store->addPrefix("event", Uri("http://purl.org/NET/c4dm/event.owl#"));
829  store->addPrefix("af", Uri("http://purl.org/ontology/af/"));
830 
831  // "MO-conformant" structure for audio files
832 
833  Node n = store->complete(Triple(Node(), Uri("a"), store->expand("mo:AudioFile")));
834  if (n != Node() && n.type == Node::URI) {
835 
836  haveAudio = true;
837 
838  } else {
839 
840  // Sonic Annotator v0.2 and below used to write this structure
841  // (which is not properly in conformance with the Music
842  // Ontology)
843 
844  Nodes sigs = store->match(Triple(Node(), Uri("a"), store->expand("mo:Signal"))).subjects();
845  foreach (Node sig, sigs) {
846  Node aa = store->complete(Triple(sig, store->expand("mo:available_as"), Node()));
847  if (aa != Node()) {
848  haveAudio = true;
849  break;
850  }
851  }
852  }
853 
854  SVDEBUG << "NOTE: RDFImporter::identifyDocumentType: haveAudio = "
855  << haveAudio << endl;
856 
857  // can't call complete() with two Nothing nodes
858  n = store->matchOnce(Triple(Node(), store->expand("event:time"), Node())).c;
859  if (n != Node()) {
860  haveAnnotations = true;
861  }
862 
863  if (!haveAnnotations) {
864  // can't call complete() with two Nothing nodes
865  n = store->matchOnce(Triple(Node(), store->expand("af:signal_feature"), Node())).c;
866  if (n != Node()) {
867  haveAnnotations = true;
868  }
869  }
870 
871  SVDEBUG << "NOTE: RDFImporter::identifyDocumentType: haveAnnotations = "
872  << haveAnnotations << endl;
873 
874  delete store;
875 
876  if (haveAudio) {
877  if (haveAnnotations) {
878  return AudioRefAndAnnotations;
879  } else {
880  return AudioRef;
881  }
882  } else {
883  if (haveAnnotations) {
884  return Annotations;
885  } else {
886  return OtherRDFDocument;
887  }
888  }
889 
890  return OtherRDFDocument;
891 }
892 
QString getErrorString() const
std::map< Model *, std::map< QString, float > > m_labelValueMap
Definition: RDFImporter.cpp:72
static FileFinder * getInstance()
Definition: FileFinder.h:43
int getSampleRate() const
Return the frame rate in frames per second.
virtual float getValueMaximum() const
static QString getKnownExtensions()
Return the file extensions that we have data file readers for, in a format suitable for use with QFil...
Definition: RDFImporter.cpp:88
virtual ~RDFImporter()
Definition: RDFImporter.cpp:98
void setRDFTypeURI(QString uri)
Set the event, feature, or signal type URI for the features contained in this model,...
Definition: Model.h:223
void getDataModelsDense(std::vector< Model * > &, ProgressReporter *)
static RDFDocumentType identifyDocumentType(QString url)
QString getLocation() const
Return the location filename or URL as passed to the constructor.
Definition: FileSource.cpp:595
std::map< QString, Model * > m_audioModelMap
Definition: RDFImporter.cpp:69
std::vector< Model * > getDataModels(ProgressReporter *reporter)
NoteModel – a concrete IntervalModel for notes.
Definition: NoteModel.h:38
RegionModel – a concrete IntervalModel for intervals associated with a value, which we call regions f...
Definition: RegionModel.h:36
void fillModel(Model *, long, long, bool, std::vector< float > &, QString)
std::vector< Model * > getDataModels(ProgressReporter *)
QString getErrorString() const
virtual void addPoint(const PointType &point)
Add a point.
Definition: SparseModel.h:704
QString m_uristring
Definition: RDFImporter.cpp:67
void waitForData()
Block on a sub-event-loop until the whole of the data has been retrieved (if it is remote).
Definition: FileSource.cpp:549
Time/value point type for use in a SparseModel or SparseValueModel.
RDFImporterImpl * m_d
Definition: RDFImporter.h:61
virtual void setSourceModel(Model *model)
Set the source model for this model.
Definition: Model.cpp:42
Text point type for use in a SparseModel.
Definition: TextModel.h:31
virtual void addPoint(const Point &point)
Add a point.
Definition: RegionModel.h:206
virtual void addPoint(const PointType &point)
Add a point.
Model is the base class for all data models that represent any sort of data on a time scale based on ...
Definition: Model.h:35
FileSource is a class used to refer to the contents of a file that may be either local or at a remote...
Definition: FileSource.h:59
void getDataModelsAudio(std::vector< Model * > &, ProgressReporter *)
void setSampleRate(int sampleRate)
Definition: RDFImporter.cpp:56
RDFImporter(QString url, int sampleRate=0)
Definition: RDFImporter.cpp:93
QString getLocalFilename() const
Return the name of the local file this FileSource refers to.
Definition: FileSource.cpp:601
#define SVDEBUG
Definition: Debug.h:42
void getDenseFeatureProperties(QString featureUri, int &sampleRate, int &windowLength, int &hopSize, int &width, int &height)
QString m_errorString
Definition: RDFImporter.cpp:68
static long realTime2Frame(const RealTime &r, unsigned int sampleRate)
Convert a RealTime into a sample frame at the given sample rate.
Definition: RealTime.cpp:442
Uri expand(QString s)
Definition: RDFImporter.cpp:65
RDFImporterImpl(QString url, int sampleRate)
void getDataModelsSparse(std::vector< Model * > &, ProgressReporter *)
void getDenseModelTitle(Model *, QString, QString)
virtual ~RDFImporterImpl()
virtual QString find(FileType type, QString location, QString lastKnownLocation="")=0
virtual void setMessage(QString text)=0
bool isOK() const
Return true if the model was constructed successfully.
void setSampleRate(int sampleRate)
BasicStore * m_store
Definition: RDFImporter.cpp:64
static RealTime fromXsdDuration(std::string xsdd)
Definition: RealTime.cpp:78
virtual void setColumn(int x, const Column &values)
Set the entire set of bin values at the given column.
RealTime represents time values to nanosecond precision with accurate arithmetic and frame-rate conve...
Definition: RealTime.h:35
bool isAvailable()
Return true if the file or remote URL exists.
Definition: FileSource.cpp:523