annotate rdf/RDFImporter.cpp @ 490:c3fb8258e34d

* Make it possible to import an entire session from an RDF document. However, at the moment the timings of events appear to be constrained by how far the audio decoder has got through its audio file at the time the event is queried -- need to investigate.
author Chris Cannam
date Fri, 21 Nov 2008 18:03:14 +0000
parents 82ab61fa9223
children 23945cdd7161
rev   line source
Chris@439 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@439 2
Chris@439 3 /*
Chris@439 4 Sonic Visualiser
Chris@439 5 An audio file viewer and annotation editor.
Chris@439 6 Centre for Digital Music, Queen Mary, University of London.
Chris@439 7 This file copyright 2008 QMUL.
Chris@439 8
Chris@439 9 This program is free software; you can redistribute it and/or
Chris@439 10 modify it under the terms of the GNU General Public License as
Chris@439 11 published by the Free Software Foundation; either version 2 of the
Chris@439 12 License, or (at your option) any later version. See the file
Chris@439 13 COPYING included with this distribution for more information.
Chris@439 14 */
Chris@439 15
Chris@439 16 #include "RDFImporter.h"
Chris@439 17
Chris@439 18 #include <map>
Chris@439 19 #include <vector>
Chris@439 20
Chris@439 21 #include <iostream>
Chris@439 22 #include <cmath>
Chris@439 23
Chris@439 24 #include "SimpleSPARQLQuery.h"
Chris@439 25
Chris@439 26 #include "base/ProgressReporter.h"
Chris@439 27 #include "base/RealTime.h"
Chris@439 28
Chris@439 29 #include "data/model/SparseOneDimensionalModel.h"
Chris@439 30 #include "data/model/SparseTimeValueModel.h"
Chris@439 31 #include "data/model/EditableDenseThreeDimensionalModel.h"
Chris@449 32 #include "data/model/NoteModel.h"
Chris@449 33 #include "data/model/RegionModel.h"
Chris@439 34
Chris@439 35 using std::cerr;
Chris@439 36 using std::endl;
Chris@439 37
Chris@439 38 class RDFImporterImpl
Chris@439 39 {
Chris@439 40 public:
Chris@439 41 RDFImporterImpl(QString url, int sampleRate);
Chris@439 42 virtual ~RDFImporterImpl();
Chris@490 43
Chris@490 44 void setSampleRate(int sampleRate) { m_sampleRate = sampleRate; }
Chris@439 45
Chris@439 46 bool isOK();
Chris@439 47 QString getErrorString() const;
Chris@439 48
Chris@490 49 QString getAudioAvailableUrl() const { return m_audioAvailableAt; }
Chris@490 50
Chris@439 51 std::vector<Model *> getDataModels(ProgressReporter *);
Chris@439 52
Chris@439 53 protected:
Chris@439 54 QString m_uristring;
Chris@439 55 QString m_errorString;
Chris@490 56 QString m_audioAvailableAt;
Chris@439 57 int m_sampleRate;
Chris@439 58
Chris@440 59 void getDataModelsSparse(std::vector<Model *> &, ProgressReporter *);
Chris@440 60 void getDataModelsDense(std::vector<Model *> &, ProgressReporter *);
Chris@440 61
Chris@440 62 void getDenseFeatureProperties(QString featureUri,
Chris@440 63 int &sampleRate, int &windowLength,
Chris@440 64 int &hopSize, int &width, int &height);
Chris@440 65
Chris@449 66
Chris@449 67 void fillModel(Model *, long, long, bool, std::vector<float> &, QString);
Chris@439 68 };
Chris@439 69
Chris@439 70
Chris@439 71 QString
Chris@439 72 RDFImporter::getKnownExtensions()
Chris@439 73 {
Chris@439 74 return "*.rdf *.n3 *.ttl";
Chris@439 75 }
Chris@439 76
Chris@439 77 RDFImporter::RDFImporter(QString url, int sampleRate) :
Chris@439 78 m_d(new RDFImporterImpl(url, sampleRate))
Chris@439 79 {
Chris@439 80 }
Chris@439 81
Chris@439 82 RDFImporter::~RDFImporter()
Chris@439 83 {
Chris@439 84 delete m_d;
Chris@439 85 }
Chris@439 86
Chris@490 87 void
Chris@490 88 RDFImporter::setSampleRate(int sampleRate)
Chris@490 89 {
Chris@490 90 m_d->setSampleRate(sampleRate);
Chris@490 91 }
Chris@490 92
Chris@439 93 bool
Chris@439 94 RDFImporter::isOK()
Chris@439 95 {
Chris@439 96 return m_d->isOK();
Chris@439 97 }
Chris@439 98
Chris@439 99 QString
Chris@439 100 RDFImporter::getErrorString() const
Chris@439 101 {
Chris@439 102 return m_d->getErrorString();
Chris@439 103 }
Chris@439 104
Chris@490 105 QString
Chris@490 106 RDFImporter::getAudioAvailableUrl() const
Chris@490 107 {
Chris@490 108 return m_d->getAudioAvailableUrl();
Chris@490 109 }
Chris@490 110
Chris@439 111 std::vector<Model *>
Chris@439 112 RDFImporter::getDataModels(ProgressReporter *r)
Chris@439 113 {
Chris@439 114 return m_d->getDataModels(r);
Chris@439 115 }
Chris@439 116
Chris@439 117 RDFImporterImpl::RDFImporterImpl(QString uri, int sampleRate) :
Chris@439 118 m_uristring(uri),
Chris@439 119 m_sampleRate(sampleRate)
Chris@439 120 {
Chris@490 121 SimpleSPARQLQuery::Value value =
Chris@490 122 SimpleSPARQLQuery::singleResultQuery
Chris@490 123 (SimpleSPARQLQuery::QueryFromSingleSource,
Chris@490 124 QString
Chris@490 125 (" PREFIX mo: <http://purl.org/ontology/mo/> "
Chris@490 126 " SELECT ?url FROM <%1> "
Chris@490 127 " WHERE { ?signal a mo:Signal ; mo:available_as ?url } "
Chris@490 128 ).arg(uri),
Chris@490 129 "url");
Chris@490 130
Chris@490 131 if (value.type == SimpleSPARQLQuery::URIValue) {
Chris@490 132 m_audioAvailableAt = value.value;
Chris@490 133 }
Chris@439 134 }
Chris@439 135
Chris@439 136 RDFImporterImpl::~RDFImporterImpl()
Chris@439 137 {
Chris@439 138 }
Chris@439 139
Chris@439 140 bool
Chris@439 141 RDFImporterImpl::isOK()
Chris@439 142 {
Chris@439 143 return (m_errorString == "");
Chris@439 144 }
Chris@439 145
Chris@439 146 QString
Chris@439 147 RDFImporterImpl::getErrorString() const
Chris@439 148 {
Chris@439 149 return m_errorString;
Chris@439 150 }
Chris@439 151
Chris@439 152 std::vector<Model *>
Chris@439 153 RDFImporterImpl::getDataModels(ProgressReporter *reporter)
Chris@439 154 {
Chris@439 155 std::vector<Model *> models;
Chris@439 156
Chris@490 157 if (m_sampleRate == 0) {
Chris@490 158 std::cerr << "RDFImporter::getDataModels: invalid sample rate" << std::endl;
Chris@490 159 return models;
Chris@490 160 }
Chris@490 161
Chris@440 162 getDataModelsDense(models, reporter);
Chris@440 163
Chris@440 164 QString error;
Chris@440 165 if (!isOK()) error = m_errorString;
Chris@440 166 m_errorString = "";
Chris@440 167
Chris@440 168 getDataModelsSparse(models, reporter);
Chris@440 169
Chris@440 170 if (isOK()) m_errorString = error;
Chris@440 171
Chris@440 172 return models;
Chris@440 173 }
Chris@440 174
Chris@440 175 void
Chris@440 176 RDFImporterImpl::getDataModelsDense(std::vector<Model *> &models,
Chris@440 177 ProgressReporter *reporter)
Chris@440 178 {
Chris@440 179 SimpleSPARQLQuery query = SimpleSPARQLQuery
Chris@489 180 (SimpleSPARQLQuery::QueryFromSingleSource,
Chris@480 181 QString
Chris@440 182 (
Chris@440 183 " PREFIX mo: <http://purl.org/ontology/mo/>"
Chris@440 184 " PREFIX af: <http://purl.org/ontology/af/>"
Chris@440 185
Chris@440 186 " SELECT ?feature ?signal_source ?feature_signal_type ?value "
Chris@440 187 " FROM <%1> "
Chris@440 188
Chris@440 189 " WHERE { "
Chris@440 190
Chris@440 191 " ?signal a mo:Signal ; "
Chris@440 192 " mo:available_as ?signal_source ; "
Chris@440 193 " af:signal_feature ?feature . "
Chris@440 194
Chris@440 195 " ?feature a ?feature_signal_type ; "
Chris@440 196 " af:value ?value . "
Chris@440 197
Chris@440 198 " } "
Chris@440 199 )
Chris@440 200 .arg(m_uristring));
Chris@440 201
Chris@440 202 SimpleSPARQLQuery::ResultList results = query.execute();
Chris@440 203
Chris@440 204 if (!query.isOK()) {
Chris@440 205 m_errorString = query.getErrorString();
Chris@440 206 return;
Chris@440 207 }
Chris@440 208
Chris@440 209 if (query.wasCancelled()) {
Chris@440 210 m_errorString = "Query cancelled";
Chris@440 211 return;
Chris@440 212 }
Chris@440 213
Chris@440 214 for (int i = 0; i < results.size(); ++i) {
Chris@440 215
Chris@440 216 QString feature = results[i]["feature"].value;
Chris@440 217 QString source = results[i]["signal_source"].value;
Chris@440 218 QString type = results[i]["feature_signal_type"].value;
Chris@440 219 QString value = results[i]["value"].value;
Chris@440 220
Chris@440 221 int sampleRate = 0;
Chris@440 222 int windowLength = 0;
Chris@440 223 int hopSize = 0;
Chris@440 224 int width = 0;
Chris@440 225 int height = 0;
Chris@440 226 getDenseFeatureProperties
Chris@440 227 (feature, sampleRate, windowLength, hopSize, width, height);
Chris@440 228
Chris@440 229 if (sampleRate != 0 && sampleRate != m_sampleRate) {
Chris@440 230 cerr << "WARNING: Sample rate in dense feature description does not match our underlying rate -- using rate from feature description" << endl;
Chris@440 231 }
Chris@440 232 if (sampleRate == 0) sampleRate = m_sampleRate;
Chris@440 233
Chris@440 234 if (hopSize == 0) {
Chris@440 235 cerr << "WARNING: Dense feature description does not specify a hop size -- assuming 1" << endl;
Chris@440 236 hopSize = 1;
Chris@440 237 }
Chris@440 238
Chris@440 239 if (height == 0) {
Chris@440 240 cerr << "WARNING: Dense feature description does not specify feature signal dimensions -- assuming one-dimensional (height = 1)" << endl;
Chris@440 241 height = 1;
Chris@440 242 }
Chris@440 243
Chris@440 244 QStringList values = value.split(' ', QString::SkipEmptyParts);
Chris@440 245
Chris@440 246 if (values.empty()) {
Chris@440 247 cerr << "WARNING: Dense feature description does not specify any values!" << endl;
Chris@440 248 continue;
Chris@440 249 }
Chris@440 250
Chris@440 251 if (height == 1) {
Chris@440 252
Chris@440 253 SparseTimeValueModel *m = new SparseTimeValueModel
Chris@440 254 (sampleRate, hopSize, false);
Chris@440 255
Chris@440 256 for (int j = 0; j < values.size(); ++j) {
Chris@440 257 float f = values[j].toFloat();
Chris@440 258 SparseTimeValueModel::Point point(j * hopSize, f, "");
Chris@440 259 m->addPoint(point);
Chris@440 260 }
Chris@440 261
Chris@440 262 models.push_back(m);
Chris@440 263
Chris@440 264 } else {
Chris@440 265
Chris@440 266 EditableDenseThreeDimensionalModel *m =
Chris@440 267 new EditableDenseThreeDimensionalModel(sampleRate, hopSize,
Chris@440 268 height, false);
Chris@440 269
Chris@440 270 EditableDenseThreeDimensionalModel::Column column;
Chris@440 271
Chris@440 272 int x = 0;
Chris@440 273
Chris@440 274 for (int j = 0; j < values.size(); ++j) {
Chris@440 275 if (j % height == 0 && !column.empty()) {
Chris@440 276 m->setColumn(x++, column);
Chris@440 277 column.clear();
Chris@440 278 }
Chris@440 279 column.push_back(values[j].toFloat());
Chris@440 280 }
Chris@440 281
Chris@440 282 if (!column.empty()) {
Chris@440 283 m->setColumn(x++, column);
Chris@440 284 }
Chris@440 285
Chris@440 286 models.push_back(m);
Chris@440 287 }
Chris@440 288 }
Chris@440 289 }
Chris@440 290
Chris@440 291 void
Chris@440 292 RDFImporterImpl::getDenseFeatureProperties(QString featureUri,
Chris@440 293 int &sampleRate, int &windowLength,
Chris@440 294 int &hopSize, int &width, int &height)
Chris@440 295 {
Chris@489 296 SimpleSPARQLQuery::QueryType s = SimpleSPARQLQuery::QueryFromSingleSource;
Chris@489 297
Chris@440 298 QString dimensionsQuery
Chris@440 299 (
Chris@440 300 " PREFIX mo: <http://purl.org/ontology/mo/>"
Chris@440 301 " PREFIX af: <http://purl.org/ontology/af/>"
Chris@440 302
Chris@440 303 " SELECT ?dimensions "
Chris@440 304 " FROM <%1> "
Chris@440 305
Chris@440 306 " WHERE { "
Chris@440 307
Chris@440 308 " <%2> af:dimensions ?dimensions . "
Chris@440 309
Chris@440 310 " } "
Chris@440 311 );
Chris@440 312
Chris@440 313 SimpleSPARQLQuery::Value dimensionsValue =
Chris@489 314 SimpleSPARQLQuery::singleResultQuery
Chris@489 315 (s, dimensionsQuery.arg(m_uristring).arg(featureUri), "dimensions");
Chris@440 316
Chris@440 317 cerr << "Dimensions = \"" << dimensionsValue.value.toStdString() << "\""
Chris@440 318 << endl;
Chris@440 319
Chris@440 320 if (dimensionsValue.value != "") {
Chris@440 321 QStringList dl = dimensionsValue.value.split(" ");
Chris@440 322 if (dl.empty()) dl.push_back(dimensionsValue.value);
Chris@440 323 if (dl.size() > 0) height = dl[0].toInt();
Chris@440 324 if (dl.size() > 1) width = dl[1].toInt();
Chris@440 325 }
Chris@440 326
Chris@440 327 QString queryTemplate
Chris@440 328 (
Chris@440 329 " PREFIX mo: <http://purl.org/ontology/mo/>"
Chris@440 330 " PREFIX af: <http://purl.org/ontology/af/>"
Chris@440 331 " PREFIX tl: <http://purl.org/NET/c4dm/timeline.owl#>"
Chris@440 332
Chris@440 333 " SELECT ?%3 "
Chris@440 334 " FROM <%1> "
Chris@440 335
Chris@440 336 " WHERE { "
Chris@440 337
Chris@440 338 " <%2> mo:time ?time . "
Chris@440 339
Chris@440 340 " ?time a tl:Interval ; "
Chris@440 341 " tl:onTimeLine ?timeline . "
Chris@440 342
Chris@440 343 " ?map tl:rangeTimeLine ?timeline . "
Chris@440 344
Chris@440 345 " ?map tl:%3 ?%3 . "
Chris@440 346
Chris@440 347 " } "
Chris@440 348 );
Chris@440 349
Chris@440 350 // Another laborious workaround for rasqal's failure to handle
Chris@440 351 // multiple optionals properly
Chris@440 352
Chris@440 353 SimpleSPARQLQuery::Value srValue =
Chris@489 354 SimpleSPARQLQuery::singleResultQuery(s,
Chris@480 355 queryTemplate
Chris@440 356 .arg(m_uristring).arg(featureUri)
Chris@440 357 .arg("sampleRate"),
Chris@440 358 "sampleRate");
Chris@440 359 if (srValue.value != "") {
Chris@440 360 sampleRate = srValue.value.toInt();
Chris@440 361 }
Chris@440 362
Chris@440 363 SimpleSPARQLQuery::Value hopValue =
Chris@489 364 SimpleSPARQLQuery::singleResultQuery(s,
Chris@480 365 queryTemplate
Chris@440 366 .arg(m_uristring).arg(featureUri)
Chris@440 367 .arg("hopSize"),
Chris@440 368 "hopSize");
Chris@440 369 if (srValue.value != "") {
Chris@440 370 hopSize = hopValue.value.toInt();
Chris@440 371 }
Chris@440 372
Chris@440 373 SimpleSPARQLQuery::Value winValue =
Chris@489 374 SimpleSPARQLQuery::singleResultQuery(s,
Chris@480 375 queryTemplate
Chris@440 376 .arg(m_uristring).arg(featureUri)
Chris@440 377 .arg("windowLength"),
Chris@440 378 "windowLength");
Chris@440 379 if (winValue.value != "") {
Chris@440 380 windowLength = winValue.value.toInt();
Chris@440 381 }
Chris@440 382
Chris@440 383 cerr << "sr = " << sampleRate << ", hop = " << hopSize << ", win = " << windowLength << endl;
Chris@440 384 }
Chris@440 385
Chris@440 386 void
Chris@440 387 RDFImporterImpl::getDataModelsSparse(std::vector<Model *> &models,
Chris@440 388 ProgressReporter *reporter)
Chris@440 389 {
Chris@489 390 SimpleSPARQLQuery::QueryType s = SimpleSPARQLQuery::QueryFromSingleSource;
Chris@489 391
Chris@439 392 // Our query is intended to retrieve every thing that has a time,
Chris@439 393 // and every feature type and value associated with a thing that
Chris@439 394 // has a time.
Chris@439 395
Chris@439 396 // We will then need to refine this big bag of results into a set
Chris@439 397 // of data models.
Chris@439 398
Chris@439 399 // Results that have different source signals should go into
Chris@439 400 // different models.
Chris@439 401
Chris@439 402 // Results that have different feature types should go into
Chris@439 403 // different models.
Chris@439 404
Chris@439 405 // Results that are sparse should go into different models from
Chris@439 406 // those that are dense (we need to examine the timestamps to
Chris@439 407 // establish this -- if the timestamps are regular, the results
Chris@439 408 // are dense -- so we can't do it as we go along, only after
Chris@439 409 // collecting all results).
Chris@439 410
Chris@439 411 // Timed things that have features associated with them should not
Chris@439 412 // appear directly in any model -- their features should appear
Chris@439 413 // instead -- and these should be different models from those used
Chris@439 414 // for timed things that do not have features.
Chris@439 415
Chris@439 416 // As we load the results, we'll push them into a partially
Chris@439 417 // structured container that maps from source signal (URI as
Chris@439 418 // string) -> feature type (likewise) -> time -> list of values.
Chris@439 419 // If the source signal or feature type is unavailable, the empty
Chris@439 420 // string will do.
Chris@439 421
Chris@449 422 QString prefixes = QString(
Chris@439 423 " PREFIX event: <http://purl.org/NET/c4dm/event.owl#>"
Chris@449 424 " PREFIX tl: <http://purl.org/NET/c4dm/timeline.owl#>"
Chris@439 425 " PREFIX mo: <http://purl.org/ontology/mo/>"
Chris@439 426 " PREFIX af: <http://purl.org/ontology/af/>"
Chris@449 427 " PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>"
Chris@449 428 );
Chris@439 429
Chris@449 430 QString queryString = prefixes + QString(
Chris@449 431
Chris@449 432 " SELECT ?signal_source ?timed_thing ?event_type ?value"
Chris@439 433 " FROM <%1>"
Chris@439 434
Chris@439 435 " WHERE {"
Chris@440 436
Chris@440 437 " ?signal mo:available_as ?signal_source ."
Chris@440 438 " ?signal a mo:Signal ."
Chris@440 439
Chris@439 440 " ?signal mo:time ?interval ."
Chris@449 441 " ?interval tl:onTimeLine ?tl ."
Chris@449 442 " ?time tl:onTimeLine ?tl ."
Chris@449 443 " ?timed_thing event:time ?time ."
Chris@440 444 " ?timed_thing a ?event_type ."
Chris@440 445
Chris@439 446 " OPTIONAL {"
Chris@440 447 " ?timed_thing af:feature ?value"
Chris@439 448 " }"
Chris@439 449 " }"
Chris@439 450
Chris@439 451 ).arg(m_uristring);
Chris@439 452
Chris@449 453 QString timeQueryString = prefixes + QString(
Chris@449 454
Chris@449 455 " SELECT ?time FROM <%1> "
Chris@449 456 " WHERE { "
Chris@449 457 " <%2> event:time ?t . "
Chris@449 458 " ?t tl:at ?time . "
Chris@449 459 " } "
Chris@449 460
Chris@449 461 ).arg(m_uristring);
Chris@449 462
Chris@449 463 QString rangeQueryString = prefixes + QString(
Chris@449 464
Chris@449 465 " SELECT ?time ?duration FROM <%1> "
Chris@449 466 " WHERE { "
Chris@449 467 " <%2> event:time ?t . "
Chris@449 468 " ?t tl:beginsAt ?time . "
Chris@449 469 " ?t tl:duration ?duration . "
Chris@449 470 " } "
Chris@449 471
Chris@449 472 ).arg(m_uristring);
Chris@449 473
Chris@449 474 QString labelQueryString = prefixes + QString(
Chris@449 475
Chris@449 476 " SELECT ?label FROM <%1> "
Chris@449 477 " WHERE { "
Chris@449 478 " <%2> rdfs:label ?label . "
Chris@449 479 " } "
Chris@449 480
Chris@449 481 ).arg(m_uristring);
Chris@449 482
Chris@489 483 SimpleSPARQLQuery query(s, queryString);
Chris@439 484 query.setProgressReporter(reporter);
Chris@439 485
Chris@439 486 cerr << "Query will be: " << queryString.toStdString() << endl;
Chris@439 487
Chris@439 488 SimpleSPARQLQuery::ResultList results = query.execute();
Chris@439 489
Chris@439 490 if (!query.isOK()) {
Chris@439 491 m_errorString = query.getErrorString();
Chris@440 492 return;
Chris@439 493 }
Chris@439 494
Chris@439 495 if (query.wasCancelled()) {
Chris@439 496 m_errorString = "Query cancelled";
Chris@440 497 return;
Chris@439 498 }
Chris@439 499
Chris@449 500
Chris@449 501
Chris@449 502 /*
Chris@449 503
Chris@449 504 This function is now only used for sparse data (for dense data
Chris@449 505 we would be in getDataModelsDense instead).
Chris@449 506
Chris@449 507 For sparse data, the determining factors in deciding what model
Chris@449 508 to use are: Do the features have values? and Do the features
Chris@449 509 have duration?
Chris@449 510
Chris@449 511 We can run through the results and check off whether we find
Chris@449 512 values and duration for each of the source+type keys, and then
Chris@449 513 run through the source+type keys pushing each of the results
Chris@449 514 into a suitable model.
Chris@449 515
Chris@449 516 Unfortunately, at this point we do not yet have any actual
Chris@449 517 timing data (time/duration) -- just the time URI.
Chris@449 518
Chris@449 519 What we _could_ do is to create one of each type of model at the
Chris@449 520 start, for each of the source+type keys, and then push each
Chris@449 521 feature into the relevant model depending on what we find out
Chris@449 522 about it. Then return only non-empty models.
Chris@449 523
Chris@449 524
Chris@449 525 */
Chris@449 526
Chris@449 527 // Map from signal source to event type to dimensionality to
Chris@449 528 // presence of duration to model ptr. Whee!
Chris@449 529 std::map<QString, std::map<QString, std::map<int, std::map<bool, Model *> > > >
Chris@449 530 modelMap;
Chris@449 531
Chris@439 532 for (int i = 0; i < results.size(); ++i) {
Chris@439 533
Chris@440 534 QString source = results[i]["signal_source"].value;
Chris@449 535 QString type = results[i]["event_type"].value;
Chris@449 536 QString thinguri = results[i]["timed_thing"].value;
Chris@449 537
Chris@449 538 RealTime time;
Chris@449 539 RealTime duration;
Chris@439 540
Chris@449 541 bool haveTime = false;
Chris@449 542 bool haveDuration = false;
Chris@439 543
Chris@449 544 QString label = SimpleSPARQLQuery::singleResultQuery
Chris@489 545 (s, labelQueryString.arg(thinguri), "label").value;
Chris@449 546
Chris@489 547 SimpleSPARQLQuery rangeQuery(s, rangeQueryString.arg(thinguri));
Chris@450 548 SimpleSPARQLQuery::ResultList rangeResults = rangeQuery.execute();
Chris@450 549 if (!rangeResults.empty()) {
Chris@450 550 // std::cerr << rangeResults.size() << " range results" << std::endl;
Chris@450 551 time = RealTime::fromXsdDuration
Chris@450 552 (rangeResults[0]["time"].value.toStdString());
Chris@450 553 duration = RealTime::fromXsdDuration
Chris@450 554 (rangeResults[0]["duration"].value.toStdString());
Chris@450 555 // std::cerr << "duration string " << rangeResults[0]["duration"].value.toStdString() << std::endl;
Chris@449 556 haveTime = true;
Chris@450 557 haveDuration = true;
Chris@449 558 } else {
Chris@450 559 QString timestring = SimpleSPARQLQuery::singleResultQuery
Chris@489 560 (s, timeQueryString.arg(thinguri), "time").value;
Chris@450 561 if (timestring != "") {
Chris@450 562 time = RealTime::fromXsdDuration(timestring.toStdString());
Chris@449 563 haveTime = true;
Chris@449 564 }
Chris@449 565 }
Chris@439 566
Chris@439 567 QString valuestring = results[i]["value"].value;
Chris@449 568 std::vector<float> values;
Chris@449 569
Chris@439 570 if (valuestring != "") {
Chris@449 571 QStringList vsl = valuestring.split(" ", QString::SkipEmptyParts);
Chris@449 572 for (int j = 0; j < vsl.size(); ++j) {
Chris@449 573 bool success = false;
Chris@449 574 float v = vsl[j].toFloat(&success);
Chris@449 575 if (success) values.push_back(v);
Chris@449 576 }
Chris@439 577 }
Chris@439 578
Chris@449 579 int dimensions = 1;
Chris@449 580 if (values.size() == 1) dimensions = 2;
Chris@449 581 else if (values.size() > 1) dimensions = 3;
Chris@449 582
Chris@449 583 Model *model = 0;
Chris@449 584
Chris@449 585 if (modelMap[source][type][dimensions].find(haveDuration) ==
Chris@449 586 modelMap[source][type][dimensions].end()) {
Chris@449 587
Chris@449 588 /*
Chris@449 589 std::cerr << "Creating new model: source = " << source.toStdString()
Chris@449 590 << ", type = " << type.toStdString() << ", dimensions = "
Chris@449 591 << dimensions << ", haveDuration = " << haveDuration
Chris@449 592 << ", time = " << time << ", duration = " << duration
Chris@449 593 << std::endl;
Chris@449 594 */
Chris@449 595
Chris@449 596 if (!haveDuration) {
Chris@449 597
Chris@449 598 if (dimensions == 1) {
Chris@449 599
Chris@449 600 // std::cerr << "SparseOneDimensionalModel" << std::endl;
Chris@449 601 model = new SparseOneDimensionalModel(m_sampleRate, 1, false);
Chris@449 602
Chris@449 603 } else if (dimensions == 2) {
Chris@449 604
Chris@449 605 // std::cerr << "SparseTimeValueModel" << std::endl;
Chris@449 606 model = new SparseTimeValueModel(m_sampleRate, 1, false);
Chris@449 607
Chris@449 608 } else {
Chris@449 609
Chris@449 610 // We don't have a three-dimensional sparse model,
Chris@449 611 // so use a note model. We do have some logic (in
Chris@449 612 // extractStructure below) for guessing whether
Chris@449 613 // this should after all have been a dense model,
Chris@449 614 // but it's hard to apply it because we don't have
Chris@449 615 // all the necessary timing data yet... hmm
Chris@449 616
Chris@449 617 // std::cerr << "NoteModel" << std::endl;
Chris@449 618 model = new NoteModel(m_sampleRate, 1, false);
Chris@449 619 }
Chris@449 620
Chris@449 621 } else { // haveDuration
Chris@449 622
Chris@449 623 if (dimensions == 1 || dimensions == 2) {
Chris@449 624
Chris@449 625 // If our units are frequency or midi pitch, we
Chris@449 626 // should be using a note model... hm
Chris@449 627
Chris@449 628 // std::cerr << "RegionModel" << std::endl;
Chris@449 629 model = new RegionModel(m_sampleRate, 1, false);
Chris@449 630
Chris@449 631 } else {
Chris@449 632
Chris@449 633 // We don't have a three-dimensional sparse model,
Chris@449 634 // so use a note model. We do have some logic (in
Chris@449 635 // extractStructure below) for guessing whether
Chris@449 636 // this should after all have been a dense model,
Chris@449 637 // but it's hard to apply it because we don't have
Chris@449 638 // all the necessary timing data yet... hmm
Chris@449 639
Chris@449 640 // std::cerr << "NoteModel" << std::endl;
Chris@449 641 model = new NoteModel(m_sampleRate, 1, false);
Chris@449 642 }
Chris@449 643 }
Chris@449 644
Chris@449 645 modelMap[source][type][dimensions][haveDuration] = model;
Chris@449 646 models.push_back(model);
Chris@449 647 }
Chris@449 648
Chris@449 649 model = modelMap[source][type][dimensions][haveDuration];
Chris@449 650
Chris@449 651 if (model) {
Chris@449 652 long ftime = RealTime::realTime2Frame(time, m_sampleRate);
Chris@449 653 long fduration = RealTime::realTime2Frame(duration, m_sampleRate);
Chris@449 654 fillModel(model, ftime, fduration, haveDuration, values, label);
Chris@439 655 }
Chris@439 656 }
Chris@439 657 }
Chris@439 658
Chris@439 659 void
Chris@449 660 RDFImporterImpl::fillModel(Model *model,
Chris@449 661 long ftime,
Chris@449 662 long fduration,
Chris@449 663 bool haveDuration,
Chris@449 664 std::vector<float> &values,
Chris@449 665 QString label)
Chris@449 666 {
Chris@449 667 SparseOneDimensionalModel *sodm =
Chris@449 668 dynamic_cast<SparseOneDimensionalModel *>(model);
Chris@449 669 if (sodm) {
Chris@449 670 SparseOneDimensionalModel::Point point(ftime, label);
Chris@449 671 sodm->addPoint(point);
Chris@449 672 return;
Chris@449 673 }
Chris@449 674
Chris@449 675 SparseTimeValueModel *stvm =
Chris@449 676 dynamic_cast<SparseTimeValueModel *>(model);
Chris@449 677 if (stvm) {
Chris@449 678 SparseTimeValueModel::Point point
Chris@449 679 (ftime, values.empty() ? 0.f : values[0], label);
Chris@449 680 stvm->addPoint(point);
Chris@449 681 return;
Chris@449 682 }
Chris@449 683
Chris@449 684 NoteModel *nm =
Chris@449 685 dynamic_cast<NoteModel *>(model);
Chris@449 686 if (nm) {
Chris@449 687 if (haveDuration) {
Chris@449 688 float value = 0.f, level = 1.f;
Chris@449 689 if (!values.empty()) {
Chris@449 690 value = values[0];
Chris@449 691 if (values.size() > 1) {
Chris@449 692 level = values[1];
Chris@449 693 }
Chris@449 694 }
Chris@449 695 NoteModel::Point point(ftime, value, fduration, level, label);
Chris@449 696 nm->addPoint(point);
Chris@449 697 } else {
Chris@449 698 float value = 0.f, duration = 1.f, level = 1.f;
Chris@449 699 if (!values.empty()) {
Chris@449 700 value = values[0];
Chris@449 701 if (values.size() > 1) {
Chris@449 702 duration = values[1];
Chris@449 703 if (values.size() > 2) {
Chris@449 704 level = values[2];
Chris@449 705 }
Chris@449 706 }
Chris@449 707 }
Chris@449 708 NoteModel::Point point(ftime, value, duration, level, label);
Chris@449 709 nm->addPoint(point);
Chris@449 710 }
Chris@449 711 return;
Chris@449 712 }
Chris@449 713
Chris@449 714 RegionModel *rm =
Chris@449 715 dynamic_cast<RegionModel *>(model);
Chris@449 716 if (rm) {
Chris@449 717 if (haveDuration) {
Chris@449 718 RegionModel::Point point
Chris@449 719 (ftime, values.empty() ? 0.f : values[0], fduration, label);
Chris@449 720 rm->addPoint(point);
Chris@449 721 } else {
Chris@449 722 // This won't actually happen -- we only create region models
Chris@449 723 // if we do have duration -- but just for completeness
Chris@449 724 float value = 0.f, duration = 1.f;
Chris@449 725 if (!values.empty()) {
Chris@449 726 value = values[0];
Chris@449 727 if (values.size() > 1) {
Chris@449 728 duration = values[1];
Chris@449 729 }
Chris@449 730 }
Chris@449 731 RegionModel::Point point(ftime, value, duration, label);
Chris@449 732 rm->addPoint(point);
Chris@449 733 }
Chris@449 734 return;
Chris@449 735 }
Chris@449 736
Chris@449 737 std::cerr << "WARNING: RDFImporterImpl::fillModel: Unknown or unexpected model type" << std::endl;
Chris@449 738 return;
Chris@449 739 }
Chris@449 740
Chris@490 741 RDFImporter::RDFDocumentType
Chris@490 742 RDFImporter::identifyDocumentType(QString url)
Chris@490 743 {
Chris@490 744 bool haveAudio = false;
Chris@490 745 bool haveAnnotations = false;
Chris@449 746
Chris@490 747 SimpleSPARQLQuery::Value value =
Chris@490 748 SimpleSPARQLQuery::singleResultQuery
Chris@490 749 (SimpleSPARQLQuery::QueryFromSingleSource,
Chris@490 750 QString
Chris@490 751 (" PREFIX mo: <http://purl.org/ontology/mo/> "
Chris@490 752 " SELECT ?url FROM <%1> "
Chris@490 753 " WHERE { ?signal a mo:Signal ; mo:available_as ?url } "
Chris@490 754 ).arg(url),
Chris@490 755 "url");
Chris@490 756
Chris@490 757 if (value.type == SimpleSPARQLQuery::URIValue) {
Chris@490 758 haveAudio = true;
Chris@490 759 }
Chris@490 760
Chris@490 761 value =
Chris@490 762 SimpleSPARQLQuery::singleResultQuery
Chris@490 763 (SimpleSPARQLQuery::QueryFromSingleSource,
Chris@490 764 QString
Chris@490 765 (" PREFIX event: <http://purl.org/NET/c4dm/event.owl#> "
Chris@490 766 " SELECT ?thing FROM <%1> "
Chris@490 767 " WHERE { ?thing event:time ?time } "
Chris@490 768 ).arg(url),
Chris@490 769 "thing");
Chris@490 770
Chris@490 771 if (value.type == SimpleSPARQLQuery::URIValue) {
Chris@490 772 haveAnnotations = true;
Chris@490 773 }
Chris@490 774
Chris@490 775 if (!haveAnnotations) {
Chris@490 776
Chris@490 777 value =
Chris@490 778 SimpleSPARQLQuery::singleResultQuery
Chris@490 779 (SimpleSPARQLQuery::QueryFromSingleSource,
Chris@490 780 QString
Chris@490 781 (" PREFIX af: <http://purl.org/ontology/af/> "
Chris@490 782 " SELECT ?thing FROM <%1> "
Chris@490 783 " WHERE { ?signal af:signal_feature ?thing } "
Chris@490 784 ).arg(url),
Chris@490 785 "thing");
Chris@490 786
Chris@490 787 if (value.type == SimpleSPARQLQuery::URIValue) {
Chris@490 788 haveAnnotations = true;
Chris@490 789 }
Chris@490 790 }
Chris@490 791
Chris@490 792 if (haveAudio) {
Chris@490 793 if (haveAnnotations) {
Chris@490 794 return AudioRefAndAnnotations;
Chris@490 795 } else {
Chris@490 796 return AudioRef;
Chris@490 797 }
Chris@490 798 } else {
Chris@490 799 if (haveAnnotations) {
Chris@490 800 return Annotations;
Chris@490 801 } else {
Chris@490 802 return OtherDocument;
Chris@490 803 }
Chris@490 804 }
Chris@490 805 }
Chris@490 806
Chris@490 807