Mercurial > hg > svcore
comparison rdf/RDFImporter.cpp @ 1752:6d09d68165a4 by-id
Further review of ById: make IDs only available when adding a model to the ById store, not by querying the item directly. This means any id encountered in the wild must have been added to the store at some point (even if later released), which simplifies reasoning about lifecycles
author | Chris Cannam |
---|---|
date | Fri, 05 Jul 2019 15:28:07 +0100 |
parents | 565575463752 |
children | d484490cdf69 |
comparison
equal
deleted
inserted
replaced
1751:77543124651b | 1752:6d09d68165a4 |
---|---|
56 void setSampleRate(sv_samplerate_t sampleRate) { m_sampleRate = sampleRate; } | 56 void setSampleRate(sv_samplerate_t sampleRate) { m_sampleRate = sampleRate; } |
57 | 57 |
58 bool isOK(); | 58 bool isOK(); |
59 QString getErrorString() const; | 59 QString getErrorString() const; |
60 | 60 |
61 std::vector<Model *> getDataModels(ProgressReporter *); | 61 std::vector<ModelId> getDataModels(ProgressReporter *); |
62 | 62 |
63 protected: | 63 protected: |
64 BasicStore *m_store; | 64 BasicStore *m_store; |
65 Uri expand(QString s) { return m_store->expand(s); } | 65 Uri expand(QString s) { return m_store->expand(s); } |
66 | 66 |
67 QString m_uristring; | 67 QString m_uristring; |
68 QString m_errorString; | 68 QString m_errorString; |
69 std::map<QString, Model *> m_audioModelMap; | 69 std::map<QString, ModelId> m_audioModelMap; |
70 sv_samplerate_t m_sampleRate; | 70 sv_samplerate_t m_sampleRate; |
71 | 71 |
72 std::map<Model *, std::map<QString, float> > m_labelValueMap; | 72 std::map<ModelId, std::map<QString, float> > m_labelValueMap; |
73 | 73 |
74 void getDataModelsAudio(std::vector<Model *> &, ProgressReporter *); | 74 void getDataModelsAudio(std::vector<ModelId> &, ProgressReporter *); |
75 void getDataModelsSparse(std::vector<Model *> &, ProgressReporter *); | 75 void getDataModelsSparse(std::vector<ModelId> &, ProgressReporter *); |
76 void getDataModelsDense(std::vector<Model *> &, ProgressReporter *); | 76 void getDataModelsDense(std::vector<ModelId> &, ProgressReporter *); |
77 | 77 |
78 void getDenseModelTitle(Model *, QString, QString); | 78 QString getDenseModelTitle(QString featureUri, QString featureTypeUri); |
79 | 79 |
80 void getDenseFeatureProperties(QString featureUri, | 80 void getDenseFeatureProperties(QString featureUri, |
81 sv_samplerate_t &sampleRate, int &windowLength, | 81 sv_samplerate_t &sampleRate, int &windowLength, |
82 int &hopSize, int &width, int &height); | 82 int &hopSize, int &width, int &height); |
83 | 83 |
84 void fillModel(Model *, sv_frame_t, sv_frame_t, | 84 void fillModel(ModelId, sv_frame_t, sv_frame_t, |
85 bool, std::vector<float> &, QString); | 85 bool, std::vector<float> &, QString); |
86 }; | 86 }; |
87 | 87 |
88 QString | 88 QString |
89 RDFImporter::getKnownExtensions() | 89 RDFImporter::getKnownExtensions() |
117 RDFImporter::getErrorString() const | 117 RDFImporter::getErrorString() const |
118 { | 118 { |
119 return m_d->getErrorString(); | 119 return m_d->getErrorString(); |
120 } | 120 } |
121 | 121 |
122 std::vector<Model *> | 122 std::vector<ModelId> |
123 RDFImporter::getDataModels(ProgressReporter *r) | 123 RDFImporter::getDataModels(ProgressReporter *r) |
124 { | 124 { |
125 return m_d->getDataModels(r); | 125 return m_d->getDataModels(r); |
126 } | 126 } |
127 | 127 |
167 RDFImporterImpl::getErrorString() const | 167 RDFImporterImpl::getErrorString() const |
168 { | 168 { |
169 return m_errorString; | 169 return m_errorString; |
170 } | 170 } |
171 | 171 |
172 std::vector<Model *> | 172 std::vector<ModelId> |
173 RDFImporterImpl::getDataModels(ProgressReporter *reporter) | 173 RDFImporterImpl::getDataModels(ProgressReporter *reporter) |
174 { | 174 { |
175 std::vector<Model *> models; | 175 std::vector<ModelId> models; |
176 | 176 |
177 getDataModelsAudio(models, reporter); | 177 getDataModelsAudio(models, reporter); |
178 | 178 |
179 if (m_sampleRate == 0) { | 179 if (m_sampleRate == 0) { |
180 m_errorString = QString("Invalid audio data model (is audio file format supported?)"); | 180 m_errorString = QString("Invalid audio data model (is audio file format supported?)"); |
204 | 204 |
205 return models; | 205 return models; |
206 } | 206 } |
207 | 207 |
208 void | 208 void |
209 RDFImporterImpl::getDataModelsAudio(std::vector<Model *> &models, | 209 RDFImporterImpl::getDataModelsAudio(std::vector<ModelId> &models, |
210 ProgressReporter *reporter) | 210 ProgressReporter *reporter) |
211 { | 211 { |
212 Nodes sigs = m_store->match | 212 Nodes sigs = m_store->match |
213 (Triple(Node(), Uri("a"), expand("mo:Signal"))).subjects(); | 213 (Triple(Node(), Uri("a"), expand("mo:Signal"))).subjects(); |
214 | 214 |
268 | 268 |
269 if (reporter) { | 269 if (reporter) { |
270 reporter->setMessage(RDFImporter::tr("Importing audio referenced in RDF...")); | 270 reporter->setMessage(RDFImporter::tr("Importing audio referenced in RDF...")); |
271 } | 271 } |
272 fs->waitForData(); | 272 fs->waitForData(); |
273 ReadOnlyWaveFileModel *newModel = new ReadOnlyWaveFileModel(*fs, m_sampleRate); | 273 auto newModel = std::make_shared<ReadOnlyWaveFileModel> |
274 (*fs, m_sampleRate); | |
274 if (newModel->isOK()) { | 275 if (newModel->isOK()) { |
275 cerr << "Successfully created wave file model from source at \"" << source << "\"" << endl; | 276 cerr << "Successfully created wave file model from source at \"" << source << "\"" << endl; |
276 models.push_back(newModel); | 277 auto modelId = ModelById::add(newModel); |
277 m_audioModelMap[signal] = newModel; | 278 models.push_back(modelId); |
279 m_audioModelMap[signal] = modelId; | |
278 if (m_sampleRate == 0) { | 280 if (m_sampleRate == 0) { |
279 m_sampleRate = newModel->getSampleRate(); | 281 m_sampleRate = newModel->getSampleRate(); |
280 } | 282 } |
281 } else { | 283 } else { |
282 m_errorString = QString("Failed to create wave file model from source at \"%1\"").arg(source); | 284 m_errorString = QString("Failed to create wave file model from source at \"%1\"").arg(source); |
283 delete newModel; | |
284 } | 285 } |
285 delete fs; | 286 delete fs; |
286 } | 287 } |
287 } | 288 } |
288 | 289 |
289 void | 290 void |
290 RDFImporterImpl::getDataModelsDense(std::vector<Model *> &models, | 291 RDFImporterImpl::getDataModelsDense(std::vector<ModelId> &models, |
291 ProgressReporter *reporter) | 292 ProgressReporter *reporter) |
292 { | 293 { |
293 if (reporter) { | 294 if (reporter) { |
294 reporter->setMessage(RDFImporter::tr("Importing dense signal data from RDF...")); | 295 reporter->setMessage(RDFImporter::tr("Importing dense signal data from RDF...")); |
295 } | 296 } |
340 continue; | 341 continue; |
341 } | 342 } |
342 | 343 |
343 if (height == 1) { | 344 if (height == 1) { |
344 | 345 |
345 SparseTimeValueModel *m = new SparseTimeValueModel | 346 auto m = std::make_shared<SparseTimeValueModel> |
346 (sampleRate, hopSize, false); | 347 (sampleRate, hopSize, false); |
347 | 348 |
348 for (int j = 0; j < values.size(); ++j) { | 349 for (int j = 0; j < values.size(); ++j) { |
349 float f = values[j].toFloat(); | 350 float f = values[j].toFloat(); |
350 Event e(j * hopSize, f, ""); | 351 Event e(j * hopSize, f, ""); |
351 m->add(e); | 352 m->add(e); |
352 } | 353 } |
353 | 354 |
354 getDenseModelTitle(m, feature, type); | 355 m->setObjectName(getDenseModelTitle(feature, type)); |
355 | |
356 m->setRDFTypeURI(type); | 356 m->setRDFTypeURI(type); |
357 | 357 models.push_back(ModelById::add(m)); |
358 models.push_back(m); | |
359 | 358 |
360 } else { | 359 } else { |
361 | 360 |
362 EditableDenseThreeDimensionalModel *m = | 361 auto m = std::make_shared<EditableDenseThreeDimensionalModel> |
363 new EditableDenseThreeDimensionalModel | |
364 (sampleRate, hopSize, height, | 362 (sampleRate, hopSize, height, |
365 EditableDenseThreeDimensionalModel::NoCompression, false); | 363 EditableDenseThreeDimensionalModel::NoCompression, false); |
366 | 364 |
367 EditableDenseThreeDimensionalModel::Column column; | 365 EditableDenseThreeDimensionalModel::Column column; |
368 | 366 |
378 | 376 |
379 if (!column.empty()) { | 377 if (!column.empty()) { |
380 m->setColumn(x++, column); | 378 m->setColumn(x++, column); |
381 } | 379 } |
382 | 380 |
383 getDenseModelTitle(m, feature, type); | 381 m->setObjectName(getDenseModelTitle(feature, type)); |
384 | |
385 m->setRDFTypeURI(type); | 382 m->setRDFTypeURI(type); |
386 | 383 models.push_back(ModelById::add(m)); |
387 models.push_back(m); | 384 } |
388 } | 385 } |
389 } | 386 } |
390 } | 387 |
391 | 388 QString |
392 void | 389 RDFImporterImpl::getDenseModelTitle(QString featureUri, |
393 RDFImporterImpl::getDenseModelTitle(Model *m, | |
394 QString featureUri, | |
395 QString featureTypeUri) | 390 QString featureTypeUri) |
396 { | 391 { |
397 Node n = m_store->complete | 392 Node n = m_store->complete |
398 (Triple(Uri(featureUri), expand("dc:title"), Node())); | 393 (Triple(Uri(featureUri), expand("dc:title"), Node())); |
399 | 394 |
400 if (n.type == Node::Literal && n.value != "") { | 395 if (n.type == Node::Literal && n.value != "") { |
401 SVDEBUG << "RDFImporterImpl::getDenseModelTitle: Title (from signal) \"" << n.value << "\"" << endl; | 396 SVDEBUG << "RDFImporterImpl::getDenseModelTitle: Title (from signal) \"" << n.value << "\"" << endl; |
402 m->setObjectName(n.value); | 397 return n.value; |
403 return; | |
404 } | 398 } |
405 | 399 |
406 n = m_store->complete | 400 n = m_store->complete |
407 (Triple(Uri(featureTypeUri), expand("dc:title"), Node())); | 401 (Triple(Uri(featureTypeUri), expand("dc:title"), Node())); |
408 | 402 |
409 if (n.type == Node::Literal && n.value != "") { | 403 if (n.type == Node::Literal && n.value != "") { |
410 SVDEBUG << "RDFImporterImpl::getDenseModelTitle: Title (from signal type) \"" << n.value << "\"" << endl; | 404 SVDEBUG << "RDFImporterImpl::getDenseModelTitle: Title (from signal type) \"" << n.value << "\"" << endl; |
411 m->setObjectName(n.value); | 405 return n.value; |
412 return; | |
413 } | 406 } |
414 | 407 |
415 SVDEBUG << "RDFImporterImpl::getDenseModelTitle: No title available for feature <" << featureUri << ">" << endl; | 408 SVDEBUG << "RDFImporterImpl::getDenseModelTitle: No title available for feature <" << featureUri << ">" << endl; |
409 return {}; | |
416 } | 410 } |
417 | 411 |
418 void | 412 void |
419 RDFImporterImpl::getDenseFeatureProperties(QString featureUri, | 413 RDFImporterImpl::getDenseFeatureProperties(QString featureUri, |
420 sv_samplerate_t &sampleRate, int &windowLength, | 414 sv_samplerate_t &sampleRate, int &windowLength, |
479 | 473 |
480 cerr << "sr = " << sampleRate << ", hop = " << hopSize << ", win = " << windowLength << endl; | 474 cerr << "sr = " << sampleRate << ", hop = " << hopSize << ", win = " << windowLength << endl; |
481 } | 475 } |
482 | 476 |
483 void | 477 void |
484 RDFImporterImpl::getDataModelsSparse(std::vector<Model *> &models, | 478 RDFImporterImpl::getDataModelsSparse(std::vector<ModelId> &models, |
485 ProgressReporter *reporter) | 479 ProgressReporter *reporter) |
486 { | 480 { |
487 if (reporter) { | 481 if (reporter) { |
488 reporter->setMessage(RDFImporter::tr("Importing event data from RDF...")); | 482 reporter->setMessage(RDFImporter::tr("Importing event data from RDF...")); |
489 } | 483 } |
508 | 502 |
509 Nodes sigs = m_store->match | 503 Nodes sigs = m_store->match |
510 (Triple(Node(), expand("a"), expand("mo:Signal"))).subjects(); | 504 (Triple(Node(), expand("a"), expand("mo:Signal"))).subjects(); |
511 | 505 |
512 // Map from timeline uri to event type to dimensionality to | 506 // Map from timeline uri to event type to dimensionality to |
513 // presence of duration to model ptr. Whee! | 507 // presence of duration to model id. Whee! |
514 std::map<QString, std::map<QString, std::map<int, std::map<bool, Model *> > > > | 508 std::map<QString, std::map<QString, std::map<int, std::map<bool, ModelId> > > > |
515 modelMap; | 509 modelMap; |
516 | 510 |
517 foreach (Node sig, sigs) { | 511 foreach (Node sig, sigs) { |
518 | 512 |
519 Node interval = m_store->complete(Triple(sig, expand("mo:time"), Node())); | 513 Node interval = m_store->complete(Triple(sig, expand("mo:time"), Node())); |
615 | 609 |
616 int dimensions = 1; | 610 int dimensions = 1; |
617 if (values.size() == 1) dimensions = 2; | 611 if (values.size() == 1) dimensions = 2; |
618 else if (values.size() > 1) dimensions = 3; | 612 else if (values.size() > 1) dimensions = 3; |
619 | 613 |
620 Model *model = nullptr; | 614 ModelId modelId; |
621 | 615 |
622 if (modelMap[timeline][type][dimensions].find(haveDuration) == | 616 if (modelMap[timeline][type][dimensions].find(haveDuration) == |
623 modelMap[timeline][type][dimensions].end()) { | 617 modelMap[timeline][type][dimensions].end()) { |
624 | 618 |
625 /* | 619 /* |
626 SVDEBUG << "Creating new model: source = " << source << ", type = " << type << ", dimensions = " | 620 SVDEBUG << "Creating new model: source = " << source << ", type = " << type << ", dimensions = " |
627 << dimensions << ", haveDuration = " << haveDuration | 621 << dimensions << ", haveDuration = " << haveDuration |
628 << ", time = " << time << ", duration = " << duration | 622 << ", time = " << time << ", duration = " << duration |
629 << endl; | 623 << endl; |
630 */ | 624 */ |
631 | 625 |
626 Model *model = nullptr; | |
627 | |
632 if (!haveDuration) { | 628 if (!haveDuration) { |
633 | 629 |
634 if (dimensions == 1) { | 630 if (dimensions == 1) { |
635 if (text) { | 631 if (text) { |
636 model = new TextModel(m_sampleRate, 1, false); | 632 model = new TextModel(m_sampleRate, 1, false); |
666 | 662 |
667 model->setRDFTypeURI(type); | 663 model->setRDFTypeURI(type); |
668 | 664 |
669 if (m_audioModelMap.find(source) != m_audioModelMap.end()) { | 665 if (m_audioModelMap.find(source) != m_audioModelMap.end()) { |
670 cerr << "source model for " << model << " is " << m_audioModelMap[source] << endl; | 666 cerr << "source model for " << model << " is " << m_audioModelMap[source] << endl; |
671 model->setSourceModel(m_audioModelMap[source]->getId()); | 667 model->setSourceModel(m_audioModelMap[source]); |
672 } | 668 } |
673 | 669 |
674 QString title = m_store->complete | 670 QString title = m_store->complete |
675 (Triple(typ, expand("dc:title"), Node())).value; | 671 (Triple(typ, expand("dc:title"), Node())).value; |
676 if (title == "") { | 672 if (title == "") { |
678 title = type; | 674 title = type; |
679 title.replace(QRegExp("^.*[/#]"), ""); | 675 title.replace(QRegExp("^.*[/#]"), ""); |
680 } | 676 } |
681 model->setObjectName(title); | 677 model->setObjectName(title); |
682 | 678 |
683 modelMap[timeline][type][dimensions][haveDuration] = model; | 679 modelId = ModelById::add(std::shared_ptr<Model>(model)); |
684 models.push_back(model); | 680 modelMap[timeline][type][dimensions][haveDuration] = modelId; |
685 } | 681 models.push_back(modelId); |
686 | 682 } |
687 model = modelMap[timeline][type][dimensions][haveDuration]; | 683 |
688 | 684 modelId = modelMap[timeline][type][dimensions][haveDuration]; |
689 if (model) { | 685 |
690 sv_frame_t ftime = RealTime::realTime2Frame(time, m_sampleRate); | 686 if (!modelId.isNone()) { |
691 sv_frame_t fduration = RealTime::realTime2Frame(duration, m_sampleRate); | 687 sv_frame_t ftime = |
692 fillModel(model, ftime, fduration, haveDuration, values, label); | 688 RealTime::realTime2Frame(time, m_sampleRate); |
689 sv_frame_t fduration = | |
690 RealTime::realTime2Frame(duration, m_sampleRate); | |
691 fillModel(modelId, ftime, fduration, | |
692 haveDuration, values, label); | |
693 } | 693 } |
694 } | 694 } |
695 } | 695 } |
696 } | 696 } |
697 } | 697 } |
698 | 698 |
699 void | 699 void |
700 RDFImporterImpl::fillModel(Model *model, | 700 RDFImporterImpl::fillModel(ModelId modelId, |
701 sv_frame_t ftime, | 701 sv_frame_t ftime, |
702 sv_frame_t fduration, | 702 sv_frame_t fduration, |
703 bool haveDuration, | 703 bool haveDuration, |
704 std::vector<float> &values, | 704 std::vector<float> &values, |
705 QString label) | 705 QString label) |
706 { | 706 { |
707 // SVDEBUG << "RDFImporterImpl::fillModel: adding point at frame " << ftime << endl; | 707 // SVDEBUG << "RDFImporterImpl::fillModel: adding point at frame " << ftime << endl; |
708 | 708 |
709 SparseOneDimensionalModel *sodm = | 709 if (auto sodm = ModelById::getAs<SparseOneDimensionalModel>(modelId)) { |
710 dynamic_cast<SparseOneDimensionalModel *>(model); | |
711 if (sodm) { | |
712 Event point(ftime, label); | 710 Event point(ftime, label); |
713 sodm->add(point); | 711 sodm->add(point); |
714 return; | 712 return; |
715 } | 713 } |
716 | 714 |
717 TextModel *tm = | 715 if (auto tm = ModelById::getAs<TextModel>(modelId)) { |
718 dynamic_cast<TextModel *>(model); | |
719 if (tm) { | |
720 Event e | 716 Event e |
721 (ftime, | 717 (ftime, |
722 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 | 718 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 |
723 label); | 719 label); |
724 tm->add(e); | 720 tm->add(e); |
725 return; | 721 return; |
726 } | 722 } |
727 | 723 |
728 SparseTimeValueModel *stvm = | 724 if (auto stvm = ModelById::getAs<SparseTimeValueModel>(modelId)) { |
729 dynamic_cast<SparseTimeValueModel *>(model); | |
730 if (stvm) { | |
731 Event e(ftime, values.empty() ? 0.f : values[0], label); | 725 Event e(ftime, values.empty() ? 0.f : values[0], label); |
732 stvm->add(e); | 726 stvm->add(e); |
733 return; | 727 return; |
734 } | 728 } |
735 | 729 |
736 NoteModel *nm = | 730 if (auto nm = ModelById::getAs<NoteModel>(modelId)) { |
737 dynamic_cast<NoteModel *>(model); | |
738 if (nm) { | |
739 if (haveDuration) { | 731 if (haveDuration) { |
740 float value = 0.f, level = 1.f; | 732 float value = 0.f, level = 1.f; |
741 if (!values.empty()) { | 733 if (!values.empty()) { |
742 value = values[0]; | 734 value = values[0]; |
743 if (values.size() > 1) { | 735 if (values.size() > 1) { |
762 nm->add(e); | 754 nm->add(e); |
763 } | 755 } |
764 return; | 756 return; |
765 } | 757 } |
766 | 758 |
767 RegionModel *rm = | 759 if (auto rm = ModelById::getAs<RegionModel>(modelId)) { |
768 dynamic_cast<RegionModel *>(model); | |
769 if (rm) { | |
770 float value = 0.f; | 760 float value = 0.f; |
771 if (values.empty()) { | 761 if (values.empty()) { |
772 // no values? map each unique label to a distinct value | 762 // no values? map each unique label to a distinct value |
773 if (m_labelValueMap[model].find(label) == m_labelValueMap[model].end()) { | 763 if (m_labelValueMap[modelId].find(label) == m_labelValueMap[modelId].end()) { |
774 m_labelValueMap[model][label] = rm->getValueMaximum() + 1.f; | 764 m_labelValueMap[modelId][label] = rm->getValueMaximum() + 1.f; |
775 } | 765 } |
776 value = m_labelValueMap[model][label]; | 766 value = m_labelValueMap[modelId][label]; |
777 } else { | 767 } else { |
778 value = values[0]; | 768 value = values[0]; |
779 } | 769 } |
780 if (haveDuration) { | 770 if (haveDuration) { |
781 Event e(ftime, value, fduration, label); | 771 Event e(ftime, value, fduration, label); |