annotate data/model/EditableDenseThreeDimensionalModel.cpp @ 533:55ad231c9db7

* try some qvectors
author Chris Cannam
date Thu, 22 Jan 2009 17:58:33 +0000
parents 1405f4a2caf3
children 6038cb6fcd30
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@533 80 model->setColumn(i, m_data.at(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@533 140 EditableDenseThreeDimensionalModel::Column
Chris@533 141 EditableDenseThreeDimensionalModel::getColumn(size_t index) const
Chris@152 142 {
Chris@152 143 QMutexLocker locker(&m_mutex);
Chris@152 144
Chris@533 145 Column result;
Chris@533 146
Chris@182 147 if (index < m_data.size()) {
Chris@533 148 result = m_data.at(index);
Chris@152 149 } else {
Chris@152 150 result.clear();
Chris@152 151 }
Chris@152 152
Chris@152 153 while (result.size() < m_yBinCount) result.push_back(m_minimum);
Chris@533 154 return result;
Chris@152 155 }
Chris@152 156
Chris@152 157 float
Chris@182 158 EditableDenseThreeDimensionalModel::getValueAt(size_t index, size_t n) const
Chris@152 159 {
Chris@152 160 QMutexLocker locker(&m_mutex);
Chris@152 161
Chris@182 162 if (index < m_data.size()) {
Chris@533 163 const Column &s = m_data.at(index);
Chris@256 164 // std::cerr << "index " << index << ", n " << n << ", res " << m_resolution << ", size " << s.size()
Chris@256 165 // << std::endl;
Chris@533 166 if (n < s.size()) return s.at(n);
Chris@152 167 }
Chris@152 168
Chris@152 169 return m_minimum;
Chris@152 170 }
Chris@152 171
Chris@152 172 void
Chris@182 173 EditableDenseThreeDimensionalModel::setColumn(size_t index,
Chris@182 174 const Column &values)
Chris@152 175 {
Chris@152 176 QMutexLocker locker(&m_mutex);
Chris@152 177
Chris@182 178 while (index >= m_data.size()) {
Chris@182 179 m_data.push_back(Column());
Chris@152 180 }
Chris@152 181
Chris@152 182 bool allChange = false;
Chris@152 183
Chris@439 184 if (values.size() > m_yBinCount) m_yBinCount = values.size();
Chris@439 185
Chris@152 186 for (size_t i = 0; i < values.size(); ++i) {
Chris@256 187 float value = values[i];
Chris@257 188 if (std::isnan(value) || std::isinf(value)) {
Chris@256 189 continue;
Chris@256 190 }
Chris@256 191 if (!m_haveExtents || value < m_minimum) {
Chris@256 192 m_minimum = value;
Chris@152 193 allChange = true;
Chris@152 194 }
Chris@256 195 if (!m_haveExtents || value > m_maximum) {
Chris@256 196 m_maximum = value;
Chris@152 197 allChange = true;
Chris@152 198 }
Chris@256 199 m_haveExtents = true;
Chris@152 200 }
Chris@152 201
Chris@152 202 m_data[index] = values;
Chris@152 203
Chris@182 204 long windowStart = index;
Chris@182 205 windowStart *= m_resolution;
Chris@182 206
Chris@152 207 if (m_notifyOnAdd) {
Chris@152 208 if (allChange) {
Chris@152 209 emit modelChanged();
Chris@152 210 } else {
Chris@152 211 emit modelChanged(windowStart, windowStart + m_resolution);
Chris@152 212 }
Chris@152 213 } else {
Chris@152 214 if (allChange) {
Chris@152 215 m_sinceLastNotifyMin = -1;
Chris@152 216 m_sinceLastNotifyMax = -1;
Chris@152 217 emit modelChanged();
Chris@152 218 } else {
Chris@152 219 if (m_sinceLastNotifyMin == -1 ||
Chris@152 220 windowStart < m_sinceLastNotifyMin) {
Chris@152 221 m_sinceLastNotifyMin = windowStart;
Chris@152 222 }
Chris@152 223 if (m_sinceLastNotifyMax == -1 ||
Chris@152 224 windowStart > m_sinceLastNotifyMax) {
Chris@152 225 m_sinceLastNotifyMax = windowStart;
Chris@152 226 }
Chris@152 227 }
Chris@152 228 }
Chris@152 229 }
Chris@152 230
Chris@152 231 QString
Chris@152 232 EditableDenseThreeDimensionalModel::getBinName(size_t n) const
Chris@152 233 {
Chris@152 234 if (m_binNames.size() > n) return m_binNames[n];
Chris@152 235 else return "";
Chris@152 236 }
Chris@152 237
Chris@152 238 void
Chris@152 239 EditableDenseThreeDimensionalModel::setBinName(size_t n, QString name)
Chris@152 240 {
Chris@152 241 while (m_binNames.size() <= n) m_binNames.push_back("");
Chris@152 242 m_binNames[n] = name;
Chris@152 243 emit modelChanged();
Chris@152 244 }
Chris@152 245
Chris@152 246 void
Chris@152 247 EditableDenseThreeDimensionalModel::setBinNames(std::vector<QString> names)
Chris@152 248 {
Chris@152 249 m_binNames = names;
Chris@152 250 emit modelChanged();
Chris@152 251 }
Chris@152 252
Chris@478 253 bool
Chris@478 254 EditableDenseThreeDimensionalModel::shouldUseLogValueScale() const
Chris@478 255 {
Chris@533 256 QVector<float> sample;
Chris@533 257 QVector<int> n;
Chris@478 258
Chris@478 259 for (int i = 0; i < 10; ++i) {
Chris@478 260 size_t index = i * 10;
Chris@478 261 if (index < m_data.size()) {
Chris@533 262 const Column &c = m_data.at(index);
Chris@478 263 while (c.size() > sample.size()) {
Chris@478 264 sample.push_back(0.f);
Chris@478 265 n.push_back(0);
Chris@478 266 }
Chris@478 267 for (int j = 0; j < c.size(); ++j) {
Chris@533 268 sample[j] += c.at(j);
Chris@478 269 ++n[j];
Chris@478 270 }
Chris@478 271 }
Chris@478 272 }
Chris@478 273
Chris@478 274 if (sample.empty()) return false;
Chris@478 275 for (int j = 0; j < sample.size(); ++j) {
Chris@478 276 if (n[j]) sample[j] /= n[j];
Chris@478 277 }
Chris@478 278
Chris@533 279 return LogRange::useLogScale(sample.toStdVector());
Chris@478 280 }
Chris@478 281
Chris@152 282 void
Chris@333 283 EditableDenseThreeDimensionalModel::setCompletion(int completion, bool update)
Chris@152 284 {
Chris@152 285 if (m_completion != completion) {
Chris@152 286 m_completion = completion;
Chris@152 287
Chris@152 288 if (completion == 100) {
Chris@152 289
Chris@152 290 m_notifyOnAdd = true; // henceforth
Chris@152 291 emit modelChanged();
Chris@152 292
Chris@152 293 } else if (!m_notifyOnAdd) {
Chris@152 294
Chris@333 295 if (update &&
Chris@333 296 m_sinceLastNotifyMin >= 0 &&
Chris@152 297 m_sinceLastNotifyMax >= 0) {
Chris@152 298 emit modelChanged(m_sinceLastNotifyMin,
Chris@152 299 m_sinceLastNotifyMax + m_resolution);
Chris@152 300 m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1;
Chris@152 301 } else {
Chris@152 302 emit completionChanged();
Chris@152 303 }
Chris@152 304 } else {
Chris@152 305 emit completionChanged();
Chris@152 306 }
Chris@152 307 }
Chris@152 308 }
Chris@152 309
Chris@318 310 QString
Chris@318 311 EditableDenseThreeDimensionalModel::toDelimitedDataString(QString delimiter) const
Chris@318 312 {
Chris@318 313 QString s;
Chris@318 314 for (size_t i = 0; i < m_data.size(); ++i) {
Chris@318 315 QStringList list;
Chris@533 316 for (size_t j = 0; j < m_data.at(i).size(); ++j) {
Chris@533 317 list << QString("%1").arg(m_data.at(i).at(j));
Chris@318 318 }
Chris@318 319 s += list.join(delimiter) + "\n";
Chris@318 320 }
Chris@318 321 return s;
Chris@318 322 }
Chris@318 323
Chris@152 324 void
Chris@152 325 EditableDenseThreeDimensionalModel::toXml(QTextStream &out,
Chris@314 326 QString indent,
Chris@314 327 QString extraAttributes) const
Chris@152 328 {
Chris@152 329 // For historical reasons we read and write "resolution" as "windowSize"
Chris@152 330
Chris@318 331 std::cerr << "EditableDenseThreeDimensionalModel::toXml" << std::endl;
Chris@318 332
Chris@314 333 Model::toXml
Chris@314 334 (out, indent,
Chris@314 335 QString("type=\"dense\" dimensions=\"3\" windowSize=\"%1\" yBinCount=\"%2\" minimum=\"%3\" maximum=\"%4\" dataset=\"%5\" %6")
Chris@152 336 .arg(m_resolution)
Chris@152 337 .arg(m_yBinCount)
Chris@152 338 .arg(m_minimum)
Chris@152 339 .arg(m_maximum)
Chris@152 340 .arg(getObjectExportId(&m_data))
Chris@152 341 .arg(extraAttributes));
Chris@152 342
Chris@152 343 out << indent;
Chris@152 344 out << QString("<dataset id=\"%1\" dimensions=\"3\" separator=\" \">\n")
Chris@152 345 .arg(getObjectExportId(&m_data));
Chris@152 346
Chris@152 347 for (size_t i = 0; i < m_binNames.size(); ++i) {
Chris@152 348 if (m_binNames[i] != "") {
Chris@152 349 out << indent + " ";
Chris@152 350 out << QString("<bin number=\"%1\" name=\"%2\"/>\n")
Chris@152 351 .arg(i).arg(m_binNames[i]);
Chris@152 352 }
Chris@152 353 }
Chris@152 354
Chris@152 355 for (size_t i = 0; i < m_data.size(); ++i) {
Chris@152 356 out << indent + " ";
Chris@152 357 out << QString("<row n=\"%1\">").arg(i);
Chris@533 358 for (size_t j = 0; j < m_data.at(i).size(); ++j) {
Chris@152 359 if (j > 0) out << " ";
Chris@533 360 out << m_data.at(i).at(j);
Chris@152 361 }
Chris@152 362 out << QString("</row>\n");
Chris@318 363 out.flush();
Chris@152 364 }
Chris@152 365
Chris@152 366 out << indent + "</dataset>\n";
Chris@152 367 }
Chris@152 368
Chris@152 369