annotate transform/Transform.cpp @ 1833:21c792334c2e sensible-delimited-data-strings

Rewrite all the DelimitedDataString stuff so as to return vectors of individual cell strings rather than having the classes add the delimiters themselves. Rename accordingly to names based on StringExport. Take advantage of this in the CSV writer code so as to properly quote cells that contain delimiter characters.
author Chris Cannam
date Fri, 03 Apr 2020 17:11:05 +0100
parents ba16388b937d
children
rev   line source
Chris@320 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@320 2
Chris@320 3 /*
Chris@320 4 Sonic Visualiser
Chris@320 5 An audio file viewer and annotation editor.
Chris@320 6 Centre for Digital Music, Queen Mary, University of London.
Chris@328 7 This file copyright 2006-2007 Chris Cannam and QMUL.
Chris@320 8
Chris@320 9 This program is free software; you can redistribute it and/or
Chris@320 10 modify it under the terms of the GNU General Public License as
Chris@320 11 published by the Free Software Foundation; either version 2 of the
Chris@320 12 License, or (at your option) any later version. See the file
Chris@320 13 COPYING included with this distribution for more information.
Chris@320 14 */
Chris@320 15
Chris@320 16 #include "Transform.h"
Chris@320 17
Chris@328 18 #include "plugin/PluginIdentifier.h"
Chris@328 19
Chris@332 20 #include "plugin/FeatureExtractionPluginFactory.h"
Chris@1138 21 #include "plugin/RealTimePluginFactory.h"
Chris@332 22
Chris@350 23 #include <QXmlAttributes>
Chris@350 24
Chris@350 25 #include <QDomDocument>
Chris@350 26 #include <QDomElement>
Chris@350 27 #include <QDomNamedNodeMap>
Chris@350 28 #include <QDomAttr>
Chris@350 29
Chris@350 30 #include <QTextStream>
Chris@350 31
Chris@350 32 #include <iostream>
Chris@350 33
Chris@328 34 Transform::Transform() :
Chris@508 35 m_summaryType(NoSummary),
Chris@328 36 m_stepSize(0),
Chris@328 37 m_blockSize(0),
Chris@328 38 m_windowType(HanningWindow),
Chris@328 39 m_sampleRate(0)
Chris@320 40 {
Chris@320 41 }
Chris@320 42
Chris@350 43 Transform::Transform(QString xml) :
Chris@508 44 m_summaryType(NoSummary),
Chris@350 45 m_stepSize(0),
Chris@350 46 m_blockSize(0),
Chris@350 47 m_windowType(HanningWindow),
Chris@350 48 m_sampleRate(0)
Chris@350 49 {
Chris@350 50 QDomDocument doc;
Chris@350 51
Chris@350 52 QString error;
Chris@350 53 int errorLine;
Chris@350 54 int errorColumn;
Chris@350 55
Chris@350 56 if (!doc.setContent(xml, false, &error, &errorLine, &errorColumn)) {
Chris@1163 57 m_errorString = QString("%1 at line %2, column %3")
Chris@1163 58 .arg(error).arg(errorLine).arg(errorColumn);
Chris@350 59 return;
Chris@350 60 }
Chris@350 61
Chris@350 62 QDomElement transformElt = doc.firstChildElement("transform");
Chris@350 63 QDomNamedNodeMap attrNodes = transformElt.attributes();
Chris@350 64 QXmlAttributes attrs;
Chris@350 65
Chris@930 66 for (int i = 0; i < attrNodes.length(); ++i) {
Chris@350 67 QDomAttr attr = attrNodes.item(i).toAttr();
Chris@350 68 if (!attr.isNull()) attrs.append(attr.name(), "", "", attr.value());
Chris@350 69 }
Chris@350 70
Chris@350 71 setFromXmlAttributes(attrs);
Chris@350 72
Chris@350 73 for (QDomElement paramElt = transformElt.firstChildElement("parameter");
Chris@350 74 !paramElt.isNull();
Chris@350 75 paramElt = paramElt.nextSiblingElement("parameter")) {
Chris@350 76
Chris@350 77 QDomNamedNodeMap paramAttrs = paramElt.attributes();
Chris@350 78
Chris@350 79 QDomAttr nameAttr = paramAttrs.namedItem("name").toAttr();
Chris@350 80 if (nameAttr.isNull() || nameAttr.value() == "") continue;
Chris@350 81
Chris@350 82 QDomAttr valueAttr = paramAttrs.namedItem("value").toAttr();
Chris@350 83 if (valueAttr.isNull() || valueAttr.value() == "") continue;
Chris@350 84
Chris@350 85 setParameter(nameAttr.value(), valueAttr.value().toFloat());
Chris@350 86 }
Chris@350 87
Chris@350 88 for (QDomElement configElt = transformElt.firstChildElement("configuration");
Chris@350 89 !configElt.isNull();
Chris@350 90 configElt = configElt.nextSiblingElement("configuration")) {
Chris@350 91
Chris@350 92 QDomNamedNodeMap configAttrs = configElt.attributes();
Chris@350 93
Chris@350 94 QDomAttr nameAttr = configAttrs.namedItem("name").toAttr();
Chris@350 95 if (nameAttr.isNull() || nameAttr.value() == "") continue;
Chris@350 96
Chris@350 97 QDomAttr valueAttr = configAttrs.namedItem("value").toAttr();
Chris@350 98 if (valueAttr.isNull() || valueAttr.value() == "") continue;
Chris@350 99
Chris@350 100 setConfigurationValue(nameAttr.value(), valueAttr.value());
Chris@350 101 }
Chris@350 102 }
Chris@350 103
Chris@320 104 Transform::~Transform()
Chris@320 105 {
Chris@320 106 }
Chris@320 107
Chris@350 108 bool
Chris@400 109 Transform::operator==(const Transform &t) const
Chris@350 110 {
Chris@583 111 bool identical =
Chris@350 112 m_id == t.m_id &&
Chris@350 113 m_parameters == t.m_parameters &&
Chris@350 114 m_configuration == t.m_configuration &&
Chris@350 115 m_program == t.m_program &&
Chris@508 116 m_summaryType == t.m_summaryType &&
Chris@350 117 m_stepSize == t.m_stepSize &&
Chris@350 118 m_blockSize == t.m_blockSize &&
Chris@350 119 m_windowType == t.m_windowType &&
Chris@350 120 m_startTime == t.m_startTime &&
Chris@350 121 m_duration == t.m_duration &&
Chris@350 122 m_sampleRate == t.m_sampleRate;
Chris@583 123 /*
Chris@690 124 SVDEBUG << "Transform::operator==: identical = " << identical << endl;
Chris@843 125 cerr << "A = " << endl;
Chris@843 126 cerr << toXmlString() << endl;
Chris@843 127 cerr << "B = " << endl;
Chris@843 128 cerr << t.toXmlString() << endl;
Chris@583 129 */
Chris@583 130 return identical;
Chris@350 131 }
Chris@350 132
Chris@400 133 bool
Chris@400 134 Transform::operator<(const Transform &t) const
Chris@400 135 {
Chris@400 136 if (m_id != t.m_id) {
Chris@400 137 return m_id < t.m_id;
Chris@400 138 }
Chris@400 139 if (m_parameters != t.m_parameters) {
Chris@400 140 return mapLessThan<QString, float>(m_parameters, t.m_parameters);
Chris@400 141 }
Chris@400 142 if (m_configuration != t.m_configuration) {
Chris@400 143 return mapLessThan<QString, QString>(m_configuration, t.m_configuration);
Chris@400 144 }
Chris@400 145 if (m_program != t.m_program) {
Chris@400 146 return m_program < t.m_program;
Chris@400 147 }
Chris@508 148 if (m_summaryType != t.m_summaryType) {
Chris@508 149 return int(m_summaryType) < int(t.m_summaryType);
Chris@508 150 }
Chris@400 151 if (m_stepSize != t.m_stepSize) {
Chris@400 152 return m_stepSize < t.m_stepSize;
Chris@400 153 }
Chris@400 154 if (m_blockSize != t.m_blockSize) {
Chris@400 155 return m_blockSize < t.m_blockSize;
Chris@400 156 }
Chris@400 157 if (m_windowType != t.m_windowType) {
Chris@400 158 return m_windowType < t.m_windowType;
Chris@400 159 }
Chris@400 160 if (m_startTime != t.m_startTime) {
Chris@400 161 return m_startTime < t.m_startTime;
Chris@400 162 }
Chris@400 163 if (m_duration != t.m_duration) {
Chris@400 164 return m_duration < t.m_duration;
Chris@400 165 }
Chris@400 166 if (m_sampleRate != t.m_sampleRate) {
Chris@400 167 return m_sampleRate < t.m_sampleRate;
Chris@400 168 }
Chris@400 169 return false;
Chris@400 170 }
Chris@400 171
Chris@350 172 void
Chris@350 173 Transform::setIdentifier(TransformId id)
Chris@350 174 {
Chris@350 175 m_id = id;
Chris@350 176 }
Chris@350 177
Chris@350 178 TransformId
Chris@350 179 Transform::getIdentifier() const
Chris@350 180 {
Chris@350 181 return m_id;
Chris@350 182 }
Chris@350 183
Chris@328 184 QString
Chris@328 185 Transform::createIdentifier(QString type, QString soName, QString label,
Chris@328 186 QString output)
Chris@328 187 {
Chris@328 188 QString pluginId = PluginIdentifier::createIdentifier(type, soName, label);
Chris@328 189 return pluginId + ":" + output;
Chris@328 190 }
Chris@328 191
Chris@328 192 void
Chris@328 193 Transform::parseIdentifier(QString identifier,
Chris@328 194 QString &type, QString &soName,
Chris@328 195 QString &label, QString &output)
Chris@328 196 {
Chris@328 197 output = identifier.section(':', 3);
Chris@328 198 PluginIdentifier::parseIdentifier(identifier.section(':', 0, 2),
Chris@328 199 type, soName, label);
Chris@328 200 }
Chris@328 201
Chris@328 202 Transform::Type
Chris@328 203 Transform::getType() const
Chris@328 204 {
Chris@1225 205 if (RealTimePluginFactory::instanceFor(getPluginIdentifier())) {
Chris@1138 206 return RealTimeEffect;
Chris@332 207 } else {
Chris@1225 208 return FeatureExtraction;
Chris@332 209 }
Chris@328 210 }
Chris@328 211
Chris@328 212 QString
Chris@328 213 Transform::getPluginIdentifier() const
Chris@328 214 {
Chris@328 215 return m_id.section(':', 0, 2);
Chris@328 216 }
Chris@328 217
Chris@328 218 QString
Chris@328 219 Transform::getOutput() const
Chris@328 220 {
Chris@328 221 return m_id.section(':', 3);
Chris@328 222 }
Chris@328 223
Chris@353 224 void
Chris@353 225 Transform::setPluginIdentifier(QString pluginIdentifier)
Chris@353 226 {
Chris@353 227 m_id = pluginIdentifier + ':' + getOutput();
Chris@353 228 }
Chris@353 229
Chris@353 230 void
Chris@353 231 Transform::setOutput(QString output)
Chris@353 232 {
Chris@353 233 m_id = getPluginIdentifier() + ':' + output;
Chris@353 234 }
Chris@353 235
Chris@353 236 TransformId
Chris@353 237 Transform::getIdentifierForPluginOutput(QString pluginIdentifier,
Chris@353 238 QString output)
Chris@353 239 {
Chris@353 240 return pluginIdentifier + ':' + output;
Chris@353 241 }
Chris@353 242
Chris@350 243 const Transform::ParameterMap &
Chris@350 244 Transform::getParameters() const
Chris@350 245 {
Chris@350 246 return m_parameters;
Chris@350 247 }
Chris@350 248
Chris@328 249 void
Chris@350 250 Transform::setParameters(const ParameterMap &pm)
Chris@328 251 {
Chris@350 252 m_parameters = pm;
Chris@350 253 }
Chris@350 254
Chris@350 255 void
Chris@350 256 Transform::setParameter(QString name, float value)
Chris@350 257 {
Chris@690 258 // SVDEBUG << "Transform::setParameter(" << name// << ") -> " << value << endl;
Chris@350 259 m_parameters[name] = value;
Chris@350 260 }
Chris@350 261
Chris@350 262 const Transform::ConfigurationMap &
Chris@350 263 Transform::getConfiguration() const
Chris@350 264 {
Chris@350 265 return m_configuration;
Chris@350 266 }
Chris@350 267
Chris@350 268 void
Chris@350 269 Transform::setConfiguration(const ConfigurationMap &cm)
Chris@350 270 {
Chris@350 271 m_configuration = cm;
Chris@350 272 }
Chris@350 273
Chris@350 274 void
Chris@350 275 Transform::setConfigurationValue(QString name, QString value)
Chris@350 276 {
Chris@690 277 SVDEBUG << "Transform::setConfigurationValue(" << name << ") -> " << value << endl;
Chris@350 278 m_configuration[name] = value;
Chris@350 279 }
Chris@350 280
Chris@350 281 QString
Chris@366 282 Transform::getPluginVersion() const
Chris@366 283 {
Chris@366 284 return m_pluginVersion;
Chris@366 285 }
Chris@366 286
Chris@366 287 void
Chris@366 288 Transform::setPluginVersion(QString version)
Chris@366 289 {
Chris@366 290 m_pluginVersion = version;
Chris@366 291 }
Chris@366 292
Chris@366 293 QString
Chris@350 294 Transform::getProgram() const
Chris@350 295 {
Chris@350 296 return m_program;
Chris@350 297 }
Chris@350 298
Chris@350 299 void
Chris@350 300 Transform::setProgram(QString program)
Chris@350 301 {
Chris@350 302 m_program = program;
Chris@350 303 }
Chris@350 304
Chris@508 305 Transform::SummaryType
Chris@508 306 Transform::getSummaryType() const
Chris@508 307 {
Chris@508 308 return m_summaryType;
Chris@508 309 }
Chris@508 310
Chris@508 311 void
Chris@508 312 Transform::setSummaryType(SummaryType type)
Chris@508 313 {
Chris@508 314 m_summaryType = type;
Chris@508 315 }
Chris@328 316
Chris@930 317 int
Chris@350 318 Transform::getStepSize() const
Chris@350 319 {
Chris@350 320 return m_stepSize;
Chris@328 321 }
Chris@350 322
Chris@350 323 void
Chris@930 324 Transform::setStepSize(int s)
Chris@350 325 {
Chris@350 326 m_stepSize = s;
Chris@350 327 }
Chris@350 328
Chris@930 329 int
Chris@350 330 Transform::getBlockSize() const
Chris@350 331 {
Chris@350 332 return m_blockSize;
Chris@350 333 }
Chris@350 334
Chris@350 335 void
Chris@930 336 Transform::setBlockSize(int s)
Chris@350 337 {
Chris@350 338 m_blockSize = s;
Chris@350 339 }
Chris@350 340
Chris@350 341 WindowType
Chris@350 342 Transform::getWindowType() const
Chris@350 343 {
Chris@350 344 return m_windowType;
Chris@350 345 }
Chris@350 346
Chris@350 347 void
Chris@350 348 Transform::setWindowType(WindowType type)
Chris@350 349 {
Chris@350 350 m_windowType = type;
Chris@350 351 }
Chris@350 352
Chris@350 353 RealTime
Chris@350 354 Transform::getStartTime() const
Chris@350 355 {
Chris@350 356 return m_startTime;
Chris@350 357 }
Chris@350 358
Chris@350 359 void
Chris@350 360 Transform::setStartTime(RealTime t)
Chris@350 361 {
Chris@350 362 m_startTime = t;
Chris@350 363 }
Chris@350 364
Chris@350 365 RealTime
Chris@350 366 Transform::getDuration() const
Chris@350 367 {
Chris@350 368 return m_duration;
Chris@350 369 }
Chris@350 370
Chris@350 371 void
Chris@350 372 Transform::setDuration(RealTime d)
Chris@350 373 {
Chris@350 374 m_duration = d;
Chris@350 375 }
Chris@350 376
Chris@1047 377 sv_samplerate_t
Chris@350 378 Transform::getSampleRate() const
Chris@350 379 {
Chris@350 380 return m_sampleRate;
Chris@350 381 }
Chris@350 382
Chris@350 383 void
Chris@1047 384 Transform::setSampleRate(sv_samplerate_t rate)
Chris@350 385 {
Chris@350 386 m_sampleRate = rate;
Chris@350 387 }
Chris@350 388
Chris@350 389 void
Chris@350 390 Transform::toXml(QTextStream &out, QString indent, QString extraAttributes) const
Chris@350 391 {
Chris@350 392 out << indent;
Chris@350 393
Chris@350 394 bool haveContent = true;
Chris@350 395 if (m_parameters.empty() && m_configuration.empty()) haveContent = false;
Chris@350 396
Chris@396 397 out << QString("<transform\n id=\"%1\"\n pluginVersion=\"%2\"\n program=\"%3\"\n stepSize=\"%4\"\n blockSize=\"%5\"\n windowType=\"%6\"\n startTime=\"%7\"\n duration=\"%8\"\n sampleRate=\"%9\"")
Chris@350 398 .arg(encodeEntities(m_id))
Chris@366 399 .arg(encodeEntities(m_pluginVersion))
Chris@350 400 .arg(encodeEntities(m_program))
Chris@350 401 .arg(m_stepSize)
Chris@350 402 .arg(m_blockSize)
Chris@350 403 .arg(encodeEntities(Window<float>::getNameForType(m_windowType).c_str()))
Chris@350 404 .arg(encodeEntities(m_startTime.toString().c_str()))
Chris@350 405 .arg(encodeEntities(m_duration.toString().c_str()))
Chris@366 406 .arg(m_sampleRate);
Chris@366 407
Chris@508 408 if (m_summaryType != NoSummary) {
Chris@508 409 out << QString("\n summaryType=\"%1\"").arg(summaryTypeToString(m_summaryType));
Chris@508 410 }
Chris@508 411
Chris@366 412 if (extraAttributes != "") {
Chris@366 413 out << " " << extraAttributes;
Chris@366 414 }
Chris@350 415
Chris@350 416 if (haveContent) {
Chris@350 417
Chris@350 418 out << ">\n";
Chris@350 419
Chris@350 420 for (ParameterMap::const_iterator i = m_parameters.begin();
Chris@350 421 i != m_parameters.end(); ++i) {
Chris@350 422 out << indent << " "
Chris@350 423 << QString("<parameter name=\"%1\" value=\"%2\"/>\n")
Chris@350 424 .arg(encodeEntities(i->first))
Chris@350 425 .arg(i->second);
Chris@350 426 }
Chris@350 427
Chris@350 428 for (ConfigurationMap::const_iterator i = m_configuration.begin();
Chris@350 429 i != m_configuration.end(); ++i) {
Chris@350 430 out << indent << " "
Chris@350 431 << QString("<configuration name=\"%1\" value=\"%2\"/>\n")
Chris@350 432 .arg(encodeEntities(i->first))
Chris@350 433 .arg(encodeEntities(i->second));
Chris@350 434 }
Chris@350 435
Chris@350 436 out << indent << "</transform>\n";
Chris@350 437
Chris@350 438 } else {
Chris@350 439
Chris@350 440 out << "/>\n";
Chris@350 441 }
Chris@350 442 }
Chris@350 443
Chris@508 444 Transform::SummaryType
Chris@508 445 Transform::stringToSummaryType(QString str)
Chris@508 446 {
Chris@508 447 str = str.toLower();
Chris@508 448 if (str == "minimum" || str == "min") return Minimum;
Chris@508 449 if (str == "maximum" || str == "max") return Maximum;
Chris@508 450 if (str == "mean") return Mean;
Chris@508 451 if (str == "median") return Median;
Chris@508 452 if (str == "mode") return Mode;
Chris@508 453 if (str == "sum") return Sum;
Chris@508 454 if (str == "variance") return Variance;
Chris@508 455 if (str == "standard-deviation" || str == "standardDeviation" ||
Chris@508 456 str == "standard deviation" || str == "sd") return StandardDeviation;
Chris@508 457 if (str == "count") return Count;
Chris@508 458 if (str == "") return NoSummary;
Chris@690 459 SVDEBUG << "Transform::stringToSummaryType: unknown summary type \""
Chris@687 460 << str << "\"" << endl;
Chris@508 461 return NoSummary;
Chris@508 462 }
Chris@508 463
Chris@508 464 QString
Chris@508 465 Transform::summaryTypeToString(SummaryType type)
Chris@508 466 {
Chris@508 467 switch (type) {
Chris@508 468 case Minimum: return "min";
Chris@508 469 case Maximum: return "max";
Chris@508 470 case Mean: return "mean";
Chris@508 471 case Median: return "median";
Chris@508 472 case Mode: return "mode";
Chris@508 473 case Sum: return "sum";
Chris@508 474 case Variance: return "variance";
Chris@508 475 case StandardDeviation: return "sd";
Chris@508 476 case Count: return "count";
Chris@508 477 case NoSummary: return "";
Chris@508 478 default:
Chris@690 479 SVDEBUG << "Transform::summaryTypeToString: unexpected summary type "
Chris@687 480 << int(type) << endl;
Chris@508 481 return "";
Chris@508 482 }
Chris@508 483 }
Chris@508 484
Chris@350 485 void
Chris@350 486 Transform::setFromXmlAttributes(const QXmlAttributes &attrs)
Chris@350 487 {
Chris@350 488 if (attrs.value("id") != "") {
Chris@350 489 setIdentifier(attrs.value("id"));
Chris@350 490 }
Chris@350 491
Chris@366 492 if (attrs.value("pluginVersion") != "") {
Chris@366 493 setPluginVersion(attrs.value("pluginVersion"));
Chris@366 494 }
Chris@366 495
Chris@350 496 if (attrs.value("program") != "") {
Chris@350 497 setProgram(attrs.value("program"));
Chris@350 498 }
Chris@350 499
Chris@350 500 if (attrs.value("stepSize") != "") {
Chris@350 501 setStepSize(attrs.value("stepSize").toInt());
Chris@350 502 }
Chris@350 503
Chris@350 504 if (attrs.value("blockSize") != "") {
Chris@350 505 setBlockSize(attrs.value("blockSize").toInt());
Chris@350 506 }
Chris@350 507
Chris@350 508 if (attrs.value("windowType") != "") {
Chris@350 509 setWindowType(Window<float>::getTypeForName
Chris@350 510 (attrs.value("windowType").toStdString()));
Chris@350 511 }
Chris@350 512
Chris@350 513 if (attrs.value("startTime") != "") {
Chris@350 514 setStartTime(RealTime::fromString(attrs.value("startTime").toStdString()));
Chris@350 515 }
Chris@350 516
Chris@350 517 if (attrs.value("duration") != "") {
Chris@988 518 setDuration(RealTime::fromString(attrs.value("duration").toStdString()));
Chris@350 519 }
Chris@350 520
Chris@350 521 if (attrs.value("sampleRate") != "") {
Chris@350 522 setSampleRate(attrs.value("sampleRate").toFloat());
Chris@350 523 }
Chris@508 524
Chris@508 525 if (attrs.value("summaryType") != "") {
Chris@508 526 setSummaryType(stringToSummaryType(attrs.value("summaryType")));
Chris@508 527 }
Chris@350 528 }
Chris@350 529