annotate data/model/EditableDenseThreeDimensionalModel.cpp @ 493:3931711b5671

* RDF importer: add model titles where possible * RDF transform factory: report whether something appears to be RDF or not (so we can avoid trying to load it as something else if the RDF query fails)
author Chris Cannam
date Tue, 25 Nov 2008 13:43:56 +0000
parents 1405f4a2caf3
children 55ad231c9db7
rev   line source
Chris@152 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@152 2
Chris@152 3 /*
Chris@152 4 Sonic Visualiser
Chris@152 5 An audio file viewer and annotation editor.
Chris@152 6 Centre for Digital Music, Queen Mary, University of London.
Chris@202 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@152 8
Chris@152 9 This program is free software; you can redistribute it and/or
Chris@152 10 modify it under the terms of the GNU General Public License as
Chris@152 11 published by the Free Software Foundation; either version 2 of the
Chris@152 12 License, or (at your option) any later version. See the file
Chris@152 13 COPYING included with this distribution for more information.
Chris@152 14 */
Chris@152 15
Chris@152 16 #include "EditableDenseThreeDimensionalModel.h"
Chris@152 17
Chris@478 18 #include "base/LogRange.h"
Chris@478 19
Chris@152 20 #include <QTextStream>
Chris@387 21 #include <QStringList>
Chris@387 22
Chris@181 23 #include <iostream>
Chris@181 24
Chris@256 25 #include <cmath>
Chris@256 26
Chris@152 27 EditableDenseThreeDimensionalModel::EditableDenseThreeDimensionalModel(size_t sampleRate,
Chris@152 28 size_t resolution,
Chris@152 29 size_t yBinCount,
Chris@152 30 bool notifyOnAdd) :
Chris@152 31 m_sampleRate(sampleRate),
Chris@152 32 m_resolution(resolution),
Chris@152 33 m_yBinCount(yBinCount),
Chris@152 34 m_minimum(0.0),
Chris@152 35 m_maximum(0.0),
Chris@256 36 m_haveExtents(false),
Chris@152 37 m_notifyOnAdd(notifyOnAdd),
Chris@152 38 m_sinceLastNotifyMin(-1),
Chris@152 39 m_sinceLastNotifyMax(-1),
Chris@152 40 m_completion(100)
Chris@152 41 {
Chris@152 42 }
Chris@152 43
Chris@152 44 bool
Chris@152 45 EditableDenseThreeDimensionalModel::isOK() const
Chris@152 46 {
Chris@152 47 return true;
Chris@152 48 }
Chris@152 49
Chris@152 50 size_t
Chris@152 51 EditableDenseThreeDimensionalModel::getSampleRate() const
Chris@152 52 {
Chris@152 53 return m_sampleRate;
Chris@152 54 }
Chris@152 55
Chris@152 56 size_t
Chris@152 57 EditableDenseThreeDimensionalModel::getStartFrame() const
Chris@152 58 {
Chris@152 59 return 0;
Chris@152 60 }
Chris@152 61
Chris@152 62 size_t
Chris@152 63 EditableDenseThreeDimensionalModel::getEndFrame() const
Chris@152 64 {
Chris@152 65 return m_resolution * m_data.size() + (m_resolution - 1);
Chris@152 66 }
Chris@152 67
Chris@152 68 Model *
Chris@152 69 EditableDenseThreeDimensionalModel::clone() const
Chris@152 70 {
Chris@152 71 EditableDenseThreeDimensionalModel *model =
Chris@152 72 new EditableDenseThreeDimensionalModel
Chris@152 73 (m_sampleRate, m_resolution, m_yBinCount);
Chris@152 74
Chris@152 75 model->m_minimum = m_minimum;
Chris@152 76 model->m_maximum = m_maximum;
Chris@256 77 model->m_haveExtents = m_haveExtents;
Chris@152 78
Chris@152 79 for (size_t i = 0; i < m_data.size(); ++i) {
Chris@182 80 model->setColumn(i, m_data[i]);
Chris@152 81 }
Chris@152 82
Chris@152 83 return model;
Chris@152 84 }
Chris@152 85
Chris@152 86 size_t
Chris@152 87 EditableDenseThreeDimensionalModel::getResolution() const
Chris@152 88 {
Chris@152 89 return m_resolution;
Chris@152 90 }
Chris@152 91
Chris@152 92 void
Chris@152 93 EditableDenseThreeDimensionalModel::setResolution(size_t sz)
Chris@152 94 {
Chris@152 95 m_resolution = sz;
Chris@152 96 }
Chris@152 97
Chris@152 98 size_t
Chris@182 99 EditableDenseThreeDimensionalModel::getWidth() const
Chris@182 100 {
Chris@182 101 return m_data.size();
Chris@182 102 }
Chris@182 103
Chris@182 104 size_t
Chris@182 105 EditableDenseThreeDimensionalModel::getHeight() const
Chris@152 106 {
Chris@152 107 return m_yBinCount;
Chris@152 108 }
Chris@152 109
Chris@152 110 void
Chris@182 111 EditableDenseThreeDimensionalModel::setHeight(size_t sz)
Chris@152 112 {
Chris@152 113 m_yBinCount = sz;
Chris@152 114 }
Chris@152 115
Chris@152 116 float
Chris@152 117 EditableDenseThreeDimensionalModel::getMinimumLevel() const
Chris@152 118 {
Chris@152 119 return m_minimum;
Chris@152 120 }
Chris@152 121
Chris@152 122 void
Chris@152 123 EditableDenseThreeDimensionalModel::setMinimumLevel(float level)
Chris@152 124 {
Chris@152 125 m_minimum = level;
Chris@152 126 }
Chris@152 127
Chris@152 128 float
Chris@152 129 EditableDenseThreeDimensionalModel::getMaximumLevel() const
Chris@152 130 {
Chris@152 131 return m_maximum;
Chris@152 132 }
Chris@152 133
Chris@152 134 void
Chris@152 135 EditableDenseThreeDimensionalModel::setMaximumLevel(float level)
Chris@152 136 {
Chris@152 137 m_maximum = level;
Chris@152 138 }
Chris@152 139
Chris@152 140 void
Chris@182 141 EditableDenseThreeDimensionalModel::getColumn(size_t index,
Chris@182 142 Column &result) const
Chris@152 143 {
Chris@152 144 QMutexLocker locker(&m_mutex);
Chris@152 145
Chris@182 146 if (index < m_data.size()) {
Chris@152 147 result = m_data[index];
Chris@152 148 } else {
Chris@152 149 result.clear();
Chris@152 150 }
Chris@152 151
Chris@152 152 while (result.size() < m_yBinCount) result.push_back(m_minimum);
Chris@152 153 }
Chris@152 154
Chris@152 155 float
Chris@182 156 EditableDenseThreeDimensionalModel::getValueAt(size_t index, size_t n) const
Chris@152 157 {
Chris@152 158 QMutexLocker locker(&m_mutex);
Chris@152 159
Chris@182 160 if (index < m_data.size()) {
Chris@182 161 const Column &s = m_data[index];
Chris@256 162 // std::cerr << "index " << index << ", n " << n << ", res " << m_resolution << ", size " << s.size()
Chris@256 163 // << std::endl;
Chris@152 164 if (n < s.size()) return s[n];
Chris@152 165 }
Chris@152 166
Chris@152 167 return m_minimum;
Chris@152 168 }
Chris@152 169
Chris@152 170 void
Chris@182 171 EditableDenseThreeDimensionalModel::setColumn(size_t index,
Chris@182 172 const Column &values)
Chris@152 173 {
Chris@152 174 QMutexLocker locker(&m_mutex);
Chris@152 175
Chris@182 176 while (index >= m_data.size()) {
Chris@182 177 m_data.push_back(Column());
Chris@152 178 }
Chris@152 179
Chris@152 180 bool allChange = false;
Chris@152 181
Chris@439 182 if (values.size() > m_yBinCount) m_yBinCount = values.size();
Chris@439 183
Chris@152 184 for (size_t i = 0; i < values.size(); ++i) {
Chris@256 185 float value = values[i];
Chris@257 186 if (std::isnan(value) || std::isinf(value)) {
Chris@256 187 continue;
Chris@256 188 }
Chris@256 189 if (!m_haveExtents || value < m_minimum) {
Chris@256 190 m_minimum = value;
Chris@152 191 allChange = true;
Chris@152 192 }
Chris@256 193 if (!m_haveExtents || value > m_maximum) {
Chris@256 194 m_maximum = value;
Chris@152 195 allChange = true;
Chris@152 196 }
Chris@256 197 m_haveExtents = true;
Chris@152 198 }
Chris@152 199
Chris@152 200 m_data[index] = values;
Chris@152 201
Chris@182 202 long windowStart = index;
Chris@182 203 windowStart *= m_resolution;
Chris@182 204
Chris@152 205 if (m_notifyOnAdd) {
Chris@152 206 if (allChange) {
Chris@152 207 emit modelChanged();
Chris@152 208 } else {
Chris@152 209 emit modelChanged(windowStart, windowStart + m_resolution);
Chris@152 210 }
Chris@152 211 } else {
Chris@152 212 if (allChange) {
Chris@152 213 m_sinceLastNotifyMin = -1;
Chris@152 214 m_sinceLastNotifyMax = -1;
Chris@152 215 emit modelChanged();
Chris@152 216 } else {
Chris@152 217 if (m_sinceLastNotifyMin == -1 ||
Chris@152 218 windowStart < m_sinceLastNotifyMin) {
Chris@152 219 m_sinceLastNotifyMin = windowStart;
Chris@152 220 }
Chris@152 221 if (m_sinceLastNotifyMax == -1 ||
Chris@152 222 windowStart > m_sinceLastNotifyMax) {
Chris@152 223 m_sinceLastNotifyMax = windowStart;
Chris@152 224 }
Chris@152 225 }
Chris@152 226 }
Chris@152 227 }
Chris@152 228
Chris@152 229 QString
Chris@152 230 EditableDenseThreeDimensionalModel::getBinName(size_t n) const
Chris@152 231 {
Chris@152 232 if (m_binNames.size() > n) return m_binNames[n];
Chris@152 233 else return "";
Chris@152 234 }
Chris@152 235
Chris@152 236 void
Chris@152 237 EditableDenseThreeDimensionalModel::setBinName(size_t n, QString name)
Chris@152 238 {
Chris@152 239 while (m_binNames.size() <= n) m_binNames.push_back("");
Chris@152 240 m_binNames[n] = name;
Chris@152 241 emit modelChanged();
Chris@152 242 }
Chris@152 243
Chris@152 244 void
Chris@152 245 EditableDenseThreeDimensionalModel::setBinNames(std::vector<QString> names)
Chris@152 246 {
Chris@152 247 m_binNames = names;
Chris@152 248 emit modelChanged();
Chris@152 249 }
Chris@152 250
Chris@478 251 bool
Chris@478 252 EditableDenseThreeDimensionalModel::shouldUseLogValueScale() const
Chris@478 253 {
Chris@478 254 std::vector<float> sample;
Chris@478 255 std::vector<int> n;
Chris@478 256
Chris@478 257 for (int i = 0; i < 10; ++i) {
Chris@478 258 size_t index = i * 10;
Chris@478 259 if (index < m_data.size()) {
Chris@478 260 const Column &c = m_data[index];
Chris@478 261 while (c.size() > sample.size()) {
Chris@478 262 sample.push_back(0.f);
Chris@478 263 n.push_back(0);
Chris@478 264 }
Chris@478 265 for (int j = 0; j < c.size(); ++j) {
Chris@478 266 sample[j] += c[j];
Chris@478 267 ++n[j];
Chris@478 268 }
Chris@478 269 }
Chris@478 270 }
Chris@478 271
Chris@478 272 if (sample.empty()) return false;
Chris@478 273 for (int j = 0; j < sample.size(); ++j) {
Chris@478 274 if (n[j]) sample[j] /= n[j];
Chris@478 275 }
Chris@478 276
Chris@478 277 return LogRange::useLogScale(sample);
Chris@478 278 }
Chris@478 279
Chris@152 280 void
Chris@333 281 EditableDenseThreeDimensionalModel::setCompletion(int completion, bool update)
Chris@152 282 {
Chris@152 283 if (m_completion != completion) {
Chris@152 284 m_completion = completion;
Chris@152 285
Chris@152 286 if (completion == 100) {
Chris@152 287
Chris@152 288 m_notifyOnAdd = true; // henceforth
Chris@152 289 emit modelChanged();
Chris@152 290
Chris@152 291 } else if (!m_notifyOnAdd) {
Chris@152 292
Chris@333 293 if (update &&
Chris@333 294 m_sinceLastNotifyMin >= 0 &&
Chris@152 295 m_sinceLastNotifyMax >= 0) {
Chris@152 296 emit modelChanged(m_sinceLastNotifyMin,
Chris@152 297 m_sinceLastNotifyMax + m_resolution);
Chris@152 298 m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1;
Chris@152 299 } else {
Chris@152 300 emit completionChanged();
Chris@152 301 }
Chris@152 302 } else {
Chris@152 303 emit completionChanged();
Chris@152 304 }
Chris@152 305 }
Chris@152 306 }
Chris@152 307
Chris@318 308 QString
Chris@318 309 EditableDenseThreeDimensionalModel::toDelimitedDataString(QString delimiter) const
Chris@318 310 {
Chris@318 311 QString s;
Chris@318 312 for (size_t i = 0; i < m_data.size(); ++i) {
Chris@318 313 QStringList list;
Chris@318 314 for (size_t j = 0; j < m_data[i].size(); ++j) {
Chris@318 315 list << QString("%1").arg(m_data[i][j]);
Chris@318 316 }
Chris@318 317 s += list.join(delimiter) + "\n";
Chris@318 318 }
Chris@318 319 return s;
Chris@318 320 }
Chris@318 321
Chris@152 322 void
Chris@152 323 EditableDenseThreeDimensionalModel::toXml(QTextStream &out,
Chris@314 324 QString indent,
Chris@314 325 QString extraAttributes) const
Chris@152 326 {
Chris@152 327 // For historical reasons we read and write "resolution" as "windowSize"
Chris@152 328
Chris@318 329 std::cerr << "EditableDenseThreeDimensionalModel::toXml" << std::endl;
Chris@318 330
Chris@314 331 Model::toXml
Chris@314 332 (out, indent,
Chris@314 333 QString("type=\"dense\" dimensions=\"3\" windowSize=\"%1\" yBinCount=\"%2\" minimum=\"%3\" maximum=\"%4\" dataset=\"%5\" %6")
Chris@152 334 .arg(m_resolution)
Chris@152 335 .arg(m_yBinCount)
Chris@152 336 .arg(m_minimum)
Chris@152 337 .arg(m_maximum)
Chris@152 338 .arg(getObjectExportId(&m_data))
Chris@152 339 .arg(extraAttributes));
Chris@152 340
Chris@152 341 out << indent;
Chris@152 342 out << QString("<dataset id=\"%1\" dimensions=\"3\" separator=\" \">\n")
Chris@152 343 .arg(getObjectExportId(&m_data));
Chris@152 344
Chris@152 345 for (size_t i = 0; i < m_binNames.size(); ++i) {
Chris@152 346 if (m_binNames[i] != "") {
Chris@152 347 out << indent + " ";
Chris@152 348 out << QString("<bin number=\"%1\" name=\"%2\"/>\n")
Chris@152 349 .arg(i).arg(m_binNames[i]);
Chris@152 350 }
Chris@152 351 }
Chris@152 352
Chris@152 353 for (size_t i = 0; i < m_data.size(); ++i) {
Chris@152 354 out << indent + " ";
Chris@152 355 out << QString("<row n=\"%1\">").arg(i);
Chris@152 356 for (size_t j = 0; j < m_data[i].size(); ++j) {
Chris@152 357 if (j > 0) out << " ";
Chris@152 358 out << m_data[i][j];
Chris@152 359 }
Chris@152 360 out << QString("</row>\n");
Chris@318 361 out.flush();
Chris@152 362 }
Chris@152 363
Chris@152 364 out << indent + "</dataset>\n";
Chris@152 365 }
Chris@152 366
Chris@152 367