annotate layer/Colour3DPlotLayer.cpp @ 454:e2a40fdadd8c

Various fixes: * Fix handling of HTTP redirects (avoiding crashes... I hope) * Fix failure to delete FFT models when a feature extraction model transformer was abandoned (also a cause of crashes in the past) * Fix deadlock when said transform was abandoned before its source model was ready because the session was being cleared (and so the source model would never be ready)
author Chris Cannam
date Fri, 28 Nov 2008 13:36:13 +0000
parents 84ada1c89510
children 035d62c4cddf
rev   line source
Chris@58 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@59 4 Sonic Visualiser
Chris@59 5 An audio file viewer and annotation editor.
Chris@59 6 Centre for Digital Music, Queen Mary, University of London.
Chris@182 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@0 8
Chris@59 9 This program is free software; you can redistribute it and/or
Chris@59 10 modify it under the terms of the GNU General Public License as
Chris@59 11 published by the Free Software Foundation; either version 2 of the
Chris@59 12 License, or (at your option) any later version. See the file
Chris@59 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@0 16 #include "Colour3DPlotLayer.h"
Chris@0 17
Chris@128 18 #include "view/View.h"
Chris@0 19 #include "base/Profiler.h"
Chris@197 20 #include "base/LogRange.h"
Chris@444 21 #include "base/RangeMapper.h"
Chris@376 22 #include "ColourMapper.h"
Chris@0 23
Chris@0 24 #include <QPainter>
Chris@0 25 #include <QImage>
Chris@0 26 #include <QRect>
Chris@316 27 #include <QTextStream>
Chris@0 28
Chris@0 29 #include <iostream>
Chris@0 30
Chris@0 31 #include <cassert>
Chris@0 32
Chris@353 33 //#define DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1
Chris@125 34
Chris@0 35
Chris@44 36 Colour3DPlotLayer::Colour3DPlotLayer() :
Chris@0 37 m_model(0),
Chris@159 38 m_cache(0),
Chris@197 39 m_cacheStart(0),
Chris@197 40 m_colourScale(LinearScale),
Chris@197 41 m_colourMap(0),
Chris@197 42 m_normalizeColumns(false),
Chris@357 43 m_normalizeVisibleArea(false),
Chris@444 44 m_invertVertical(false),
Chris@444 45 m_miny(0),
Chris@444 46 m_maxy(0)
Chris@0 47 {
Chris@44 48
Chris@0 49 }
Chris@0 50
Chris@0 51 Colour3DPlotLayer::~Colour3DPlotLayer()
Chris@0 52 {
Chris@0 53 }
Chris@0 54
Chris@0 55 void
Chris@0 56 Colour3DPlotLayer::setModel(const DenseThreeDimensionalModel *model)
Chris@0 57 {
Chris@193 58 if (m_model == model) return;
Chris@193 59 const DenseThreeDimensionalModel *oldModel = m_model;
Chris@0 60 m_model = model;
Chris@0 61 if (!m_model || !m_model->isOK()) return;
Chris@0 62
Chris@320 63 connectSignals(m_model);
Chris@0 64
Chris@0 65 connect(m_model, SIGNAL(modelChanged()), this, SLOT(cacheInvalid()));
Chris@0 66 connect(m_model, SIGNAL(modelChanged(size_t, size_t)),
Chris@0 67 this, SLOT(cacheInvalid(size_t, size_t)));
Chris@0 68
Chris@0 69 emit modelReplaced();
Chris@193 70 emit sliceableModelReplaced(oldModel, model);
Chris@0 71 }
Chris@0 72
Chris@0 73 void
Chris@0 74 Colour3DPlotLayer::cacheInvalid()
Chris@0 75 {
Chris@0 76 delete m_cache;
Chris@0 77 m_cache = 0;
Chris@0 78 }
Chris@0 79
Chris@0 80 void
Chris@0 81 Colour3DPlotLayer::cacheInvalid(size_t, size_t)
Chris@0 82 {
Chris@0 83 cacheInvalid();
Chris@0 84 }
Chris@0 85
Chris@159 86 Layer::PropertyList
Chris@159 87 Colour3DPlotLayer::getProperties() const
Chris@159 88 {
Chris@159 89 PropertyList list;
Chris@197 90 list.push_back("Colour");
Chris@159 91 list.push_back("Colour Scale");
Chris@197 92 list.push_back("Normalize Columns");
Chris@197 93 list.push_back("Normalize Visible Area");
Chris@357 94 list.push_back("Invert Vertical Scale");
Chris@159 95 return list;
Chris@159 96 }
Chris@159 97
Chris@159 98 QString
Chris@159 99 Colour3DPlotLayer::getPropertyLabel(const PropertyName &name) const
Chris@159 100 {
Chris@197 101 if (name == "Colour") return tr("Colour");
Chris@197 102 if (name == "Colour Scale") return tr("Scale");
Chris@197 103 if (name == "Normalize Columns") return tr("Normalize Columns");
Chris@197 104 if (name == "Normalize Visible Area") return tr("Normalize Visible Area");
Chris@357 105 if (name == "Invert Vertical Scale") return tr("Invert Vertical Scale");
Chris@159 106 return "";
Chris@159 107 }
Chris@159 108
Chris@346 109 QString
Chris@346 110 Colour3DPlotLayer::getPropertyIconName(const PropertyName &name) const
Chris@346 111 {
Chris@346 112 if (name == "Normalize Columns") return "normalise-columns";
Chris@346 113 if (name == "Normalize Visible Area") return "normalise";
Chris@357 114 if (name == "Invert Vertical Scale") return "invert-vertical";
Chris@346 115 return "";
Chris@346 116 }
Chris@346 117
Chris@159 118 Layer::PropertyType
Chris@159 119 Colour3DPlotLayer::getPropertyType(const PropertyName &name) const
Chris@159 120 {
Chris@197 121 if (name == "Normalize Columns") return ToggleProperty;
Chris@197 122 if (name == "Normalize Visible Area") return ToggleProperty;
Chris@357 123 if (name == "Invert Vertical Scale") return ToggleProperty;
Chris@159 124 return ValueProperty;
Chris@159 125 }
Chris@159 126
Chris@159 127 QString
Chris@159 128 Colour3DPlotLayer::getPropertyGroupName(const PropertyName &name) const
Chris@159 129 {
Chris@197 130 if (name == "Normalize Columns" ||
Chris@197 131 name == "Normalize Visible Area" ||
Chris@357 132 name == "Invert Vertical Scale" ||
Chris@197 133 name == "Colour Scale") return tr("Scale");
Chris@159 134 return QString();
Chris@159 135 }
Chris@159 136
Chris@159 137 int
Chris@159 138 Colour3DPlotLayer::getPropertyRangeAndValue(const PropertyName &name,
Chris@216 139 int *min, int *max, int *deflt) const
Chris@159 140 {
Chris@216 141 int val = 0;
Chris@159 142
Chris@216 143 int garbage0, garbage1, garbage2;
Chris@159 144 if (!min) min = &garbage0;
Chris@159 145 if (!max) max = &garbage1;
Chris@216 146 if (!deflt) deflt = &garbage2;
Chris@159 147
Chris@159 148 if (name == "Colour Scale") {
Chris@159 149
Chris@159 150 *min = 0;
Chris@197 151 *max = 2;
Chris@216 152 *deflt = (int)LinearScale;
Chris@159 153
Chris@216 154 val = (int)m_colourScale;
Chris@159 155
Chris@197 156 } else if (name == "Colour") {
Chris@197 157
Chris@197 158 *min = 0;
Chris@197 159 *max = ColourMapper::getColourMapCount() - 1;
Chris@216 160 *deflt = 0;
Chris@197 161
Chris@216 162 val = m_colourMap;
Chris@197 163
Chris@197 164 } else if (name == "Normalize Columns") {
Chris@197 165
Chris@216 166 *deflt = 0;
Chris@216 167 val = (m_normalizeColumns ? 1 : 0);
Chris@197 168
Chris@197 169 } else if (name == "Normalize Visible Area") {
Chris@197 170
Chris@216 171 *deflt = 0;
Chris@216 172 val = (m_normalizeVisibleArea ? 1 : 0);
Chris@197 173
Chris@357 174 } else if (name == "Invert Vertical Scale") {
Chris@357 175
Chris@357 176 *deflt = 0;
Chris@357 177 val = (m_invertVertical ? 1 : 0);
Chris@357 178
Chris@159 179 } else {
Chris@216 180 val = Layer::getPropertyRangeAndValue(name, min, max, deflt);
Chris@159 181 }
Chris@159 182
Chris@216 183 return val;
Chris@159 184 }
Chris@159 185
Chris@159 186 QString
Chris@159 187 Colour3DPlotLayer::getPropertyValueLabel(const PropertyName &name,
Chris@159 188 int value) const
Chris@159 189 {
Chris@197 190 if (name == "Colour") {
Chris@197 191 return ColourMapper::getColourMapName(value);
Chris@197 192 }
Chris@159 193 if (name == "Colour Scale") {
Chris@159 194 switch (value) {
Chris@159 195 default:
Chris@198 196 case 0: return tr("Linear");
Chris@198 197 case 1: return tr("Log");
Chris@198 198 case 2: return tr("+/-1");
Chris@159 199 }
Chris@159 200 }
Chris@159 201 return tr("<unknown>");
Chris@159 202 }
Chris@159 203
Chris@159 204 void
Chris@159 205 Colour3DPlotLayer::setProperty(const PropertyName &name, int value)
Chris@159 206 {
Chris@159 207 if (name == "Colour Scale") {
Chris@159 208 switch (value) {
Chris@159 209 default:
Chris@159 210 case 0: setColourScale(LinearScale); break;
Chris@197 211 case 1: setColourScale(LogScale); break;
Chris@197 212 case 2: setColourScale(PlusMinusOneScale); break;
Chris@159 213 }
Chris@197 214 } else if (name == "Colour") {
Chris@197 215 setColourMap(value);
Chris@197 216 } else if (name == "Normalize Columns") {
Chris@197 217 setNormalizeColumns(value ? true : false);
Chris@197 218 } else if (name == "Normalize Visible Area") {
Chris@197 219 setNormalizeVisibleArea(value ? true : false);
Chris@357 220 } else if (name == "Invert Vertical Scale") {
Chris@357 221 setInvertVertical(value ? true : false);
Chris@159 222 }
Chris@159 223 }
Chris@159 224
Chris@159 225 void
Chris@159 226 Colour3DPlotLayer::setColourScale(ColourScale scale)
Chris@159 227 {
Chris@159 228 if (m_colourScale == scale) return;
Chris@159 229 m_colourScale = scale;
Chris@159 230 cacheInvalid();
Chris@159 231 emit layerParametersChanged();
Chris@159 232 }
Chris@159 233
Chris@197 234 void
Chris@197 235 Colour3DPlotLayer::setColourMap(int map)
Chris@197 236 {
Chris@197 237 if (m_colourMap == map) return;
Chris@197 238 m_colourMap = map;
Chris@197 239 cacheInvalid();
Chris@197 240 emit layerParametersChanged();
Chris@197 241 }
Chris@197 242
Chris@197 243 void
Chris@197 244 Colour3DPlotLayer::setNormalizeColumns(bool n)
Chris@197 245 {
Chris@197 246 if (m_normalizeColumns == n) return;
Chris@197 247 m_normalizeColumns = n;
Chris@197 248 cacheInvalid();
Chris@197 249 emit layerParametersChanged();
Chris@197 250 }
Chris@197 251
Chris@197 252 bool
Chris@197 253 Colour3DPlotLayer::getNormalizeColumns() const
Chris@197 254 {
Chris@197 255 return m_normalizeColumns;
Chris@197 256 }
Chris@197 257
Chris@197 258 void
Chris@197 259 Colour3DPlotLayer::setNormalizeVisibleArea(bool n)
Chris@197 260 {
Chris@197 261 if (m_normalizeVisibleArea == n) return;
Chris@197 262 m_normalizeVisibleArea = n;
Chris@197 263 cacheInvalid();
Chris@197 264 emit layerParametersChanged();
Chris@197 265 }
Chris@197 266
Chris@197 267 bool
Chris@197 268 Colour3DPlotLayer::getNormalizeVisibleArea() const
Chris@197 269 {
Chris@197 270 return m_normalizeVisibleArea;
Chris@197 271 }
Chris@197 272
Chris@357 273 void
Chris@357 274 Colour3DPlotLayer::setInvertVertical(bool n)
Chris@357 275 {
Chris@357 276 if (m_invertVertical == n) return;
Chris@357 277 m_invertVertical = n;
Chris@357 278 cacheInvalid();
Chris@357 279 emit layerParametersChanged();
Chris@357 280 }
Chris@357 281
Chris@357 282 bool
Chris@357 283 Colour3DPlotLayer::getInvertVertical() const
Chris@357 284 {
Chris@357 285 return m_invertVertical;
Chris@357 286 }
Chris@357 287
Chris@25 288 bool
Chris@44 289 Colour3DPlotLayer::isLayerScrollable(const View *v) const
Chris@25 290 {
Chris@197 291 if (m_normalizeVisibleArea) return false;
Chris@25 292 QPoint discard;
Chris@44 293 return !v->shouldIlluminateLocalFeatures(this, discard);
Chris@25 294 }
Chris@25 295
Chris@444 296 bool
Chris@444 297 Colour3DPlotLayer::getValueExtents(float &min, float &max,
Chris@444 298 bool &logarithmic, QString &unit) const
Chris@444 299 {
Chris@444 300 if (!m_model) return false;
Chris@444 301
Chris@444 302 min = 0;
Chris@444 303 max = m_model->getHeight();
Chris@444 304
Chris@444 305 logarithmic = false;
Chris@444 306 unit = "";
Chris@444 307
Chris@444 308 return true;
Chris@444 309 }
Chris@444 310
Chris@444 311 bool
Chris@444 312 Colour3DPlotLayer::getDisplayExtents(float &min, float &max) const
Chris@444 313 {
Chris@444 314 if (!m_model) return false;
Chris@444 315
Chris@444 316 min = m_miny;
Chris@444 317 max = m_maxy;
Chris@444 318 if (max <= min) {
Chris@444 319 min = 0;
Chris@444 320 max = m_model->getHeight();
Chris@444 321 }
Chris@444 322 if (min < 0) min = 0;
Chris@444 323 if (max > m_model->getHeight()) max = m_model->getHeight();
Chris@444 324
Chris@444 325 return true;
Chris@444 326 }
Chris@444 327
Chris@444 328 bool
Chris@444 329 Colour3DPlotLayer::setDisplayExtents(float min, float max)
Chris@444 330 {
Chris@444 331 if (!m_model) return false;
Chris@444 332
Chris@444 333 m_miny = lrintf(min);
Chris@444 334 m_maxy = lrintf(max);
Chris@444 335
Chris@444 336 emit layerParametersChanged();
Chris@444 337 return true;
Chris@444 338 }
Chris@444 339
Chris@444 340 int
Chris@444 341 Colour3DPlotLayer::getVerticalZoomSteps(int &defaultStep) const
Chris@444 342 {
Chris@444 343 if (!m_model) return 0;
Chris@444 344
Chris@444 345 defaultStep = 0;
Chris@444 346 int h = m_model->getHeight();
Chris@444 347 return h;
Chris@444 348 }
Chris@444 349
Chris@444 350 int
Chris@444 351 Colour3DPlotLayer::getCurrentVerticalZoomStep() const
Chris@444 352 {
Chris@444 353 if (!m_model) return 0;
Chris@444 354
Chris@444 355 float min, max;
Chris@444 356 getDisplayExtents(min, max);
Chris@444 357 return m_model->getHeight() - lrintf(max - min);
Chris@444 358 }
Chris@444 359
Chris@444 360 void
Chris@444 361 Colour3DPlotLayer::setVerticalZoomStep(int step)
Chris@444 362 {
Chris@444 363 if (!m_model) return;
Chris@444 364
Chris@445 365 // std::cerr << "Colour3DPlotLayer::setVerticalZoomStep(" <<step <<"): before: miny = " << m_miny << ", maxy = " << m_maxy << std::endl;
Chris@444 366
Chris@444 367 int dist = m_model->getHeight() - step;
Chris@444 368 if (dist < 1) dist = 1;
Chris@444 369 float centre = m_miny + (float(m_maxy) - float(m_miny)) / 2.f;
Chris@444 370 m_miny = lrintf(centre - float(dist)/2);
Chris@444 371 if (m_miny < 0) m_miny = 0;
Chris@444 372 m_maxy = m_miny + dist;
Chris@444 373 if (m_maxy > m_model->getHeight()) m_maxy = m_model->getHeight();
Chris@444 374
Chris@445 375 // std::cerr << "Colour3DPlotLayer::setVerticalZoomStep(" <<step <<"): after: miny = " << m_miny << ", maxy = " << m_maxy << std::endl;
Chris@444 376
Chris@444 377 emit layerParametersChanged();
Chris@444 378 }
Chris@444 379
Chris@444 380 RangeMapper *
Chris@444 381 Colour3DPlotLayer::getNewVerticalZoomRangeMapper() const
Chris@444 382 {
Chris@444 383 if (!m_model) return 0;
Chris@444 384
Chris@444 385 return new LinearRangeMapper(0, m_model->getHeight(),
Chris@444 386 0, m_model->getHeight(), "");
Chris@444 387 }
Chris@444 388
Chris@25 389 QString
Chris@44 390 Colour3DPlotLayer::getFeatureDescription(View *v, QPoint &pos) const
Chris@25 391 {
Chris@25 392 if (!m_model) return "";
Chris@25 393
Chris@25 394 int x = pos.x();
Chris@25 395 int y = pos.y();
Chris@25 396
Chris@25 397 size_t modelStart = m_model->getStartFrame();
Chris@130 398 size_t modelResolution = m_model->getResolution();
Chris@25 399
Chris@159 400 float srRatio =
Chris@159 401 float(v->getViewManager()->getMainModelSampleRate()) /
Chris@159 402 float(m_model->getSampleRate());
Chris@159 403
Chris@160 404 int sx0 = int((v->getFrameForX(x) / srRatio - long(modelStart)) /
Chris@160 405 long(modelResolution));
Chris@25 406
Chris@160 407 int f0 = sx0 * modelResolution;
Chris@160 408 int f1 = f0 + modelResolution;
Chris@160 409
Chris@447 410 int sh = m_model->getHeight();
Chris@447 411
Chris@447 412 int symin = m_miny;
Chris@447 413 int symax = m_maxy;
Chris@447 414 if (symax <= symin) {
Chris@447 415 symin = 0;
Chris@447 416 symax = sh;
Chris@447 417 }
Chris@447 418 if (symin < 0) symin = 0;
Chris@447 419 if (symax > sh) symax = sh;
Chris@447 420
Chris@447 421 float binHeight = float(v->height()) / (symax - symin);
Chris@447 422 int sy = int((v->height() - y) / binHeight) + symin;
Chris@25 423
Chris@357 424 if (m_invertVertical) sy = m_model->getHeight() - sy - 1;
Chris@357 425
Chris@160 426 float value = m_model->getValueAt(sx0, sy);
Chris@159 427
Chris@159 428 // std::cerr << "bin value (" << sx0 << "," << sy << ") is " << value << std::endl;
Chris@25 429
Chris@25 430 QString binName = m_model->getBinName(sy);
Chris@25 431 if (binName == "") binName = QString("[%1]").arg(sy + 1);
Chris@25 432 else binName = QString("%1 [%2]").arg(binName).arg(sy + 1);
Chris@25 433
Chris@25 434 QString text = tr("Time:\t%1 - %2\nBin:\t%3\nValue:\t%4")
Chris@160 435 .arg(RealTime::frame2RealTime(f0, m_model->getSampleRate())
Chris@25 436 .toText(true).c_str())
Chris@160 437 .arg(RealTime::frame2RealTime(f1, m_model->getSampleRate())
Chris@25 438 .toText(true).c_str())
Chris@25 439 .arg(binName)
Chris@25 440 .arg(value);
Chris@25 441
Chris@25 442 return text;
Chris@25 443 }
Chris@25 444
Chris@25 445 int
Chris@248 446 Colour3DPlotLayer::getColourScaleWidth(QPainter &) const
Chris@159 447 {
Chris@159 448 int cw = 20;
Chris@159 449 return cw;
Chris@159 450 }
Chris@159 451
Chris@159 452 int
Chris@248 453 Colour3DPlotLayer::getVerticalScaleWidth(View *, QPainter &paint) const
Chris@25 454 {
Chris@25 455 if (!m_model) return 0;
Chris@25 456
Chris@160 457 QString sampleText = QString("[%1]").arg(m_model->getHeight());
Chris@25 458 int tw = paint.fontMetrics().width(sampleText);
Chris@98 459 bool another = false;
Chris@25 460
Chris@160 461 for (size_t i = 0; i < m_model->getHeight(); ++i) {
Chris@25 462 if (m_model->getBinName(i).length() > sampleText.length()) {
Chris@25 463 sampleText = m_model->getBinName(i);
Chris@98 464 another = true;
Chris@25 465 }
Chris@25 466 }
Chris@98 467 if (another) {
Chris@25 468 tw = std::max(tw, paint.fontMetrics().width(sampleText));
Chris@25 469 }
Chris@25 470
Chris@159 471 return tw + 13 + getColourScaleWidth(paint);
Chris@25 472 }
Chris@25 473
Chris@25 474 void
Chris@44 475 Colour3DPlotLayer::paintVerticalScale(View *v, QPainter &paint, QRect rect) const
Chris@25 476 {
Chris@25 477 if (!m_model) return;
Chris@25 478
Chris@25 479 int h = rect.height(), w = rect.width();
Chris@25 480
Chris@159 481 int cw = getColourScaleWidth(paint);
Chris@159 482
Chris@159 483 int ch = h - 20;
Chris@159 484 if (ch > 20 && m_cache) {
Chris@159 485
Chris@447 486 float min = m_model->getMinimumLevel();
Chris@447 487 float max = m_model->getMaximumLevel();
Chris@447 488
Chris@447 489 float mmin = min;
Chris@447 490 float mmax = max;
Chris@447 491
Chris@447 492 if (m_colourScale == LogScale) {
Chris@447 493 LogRange::mapRange(mmin, mmax);
Chris@447 494 } else if (m_colourScale == PlusMinusOneScale) {
Chris@447 495 mmin = -1.f;
Chris@447 496 mmax = 1.f;
Chris@447 497 }
Chris@447 498
Chris@447 499 if (max == min) max = min + 1.0;
Chris@447 500
Chris@287 501 paint.setPen(v->getForeground());
Chris@447 502 paint.drawRect(4, 10, cw - 8, ch+1);
Chris@159 503
Chris@446 504 for (int y = 0; y < ch; ++y) {
Chris@447 505 float value = ((max - min) * (ch - y - 1)) / ch + min;
Chris@447 506 if (m_colourScale == LogScale) {
Chris@447 507 value = LogRange::map(value);
Chris@447 508 }
Chris@447 509 int pixel = int(((value - mmin) * 256) / (mmax - mmin));
Chris@447 510 QRgb c = m_cache->color(pixel);
Chris@447 511 // QRgb c = m_cache->color(((ch - y) * 255) / ch);
Chris@159 512 paint.setPen(QColor(qRed(c), qGreen(c), qBlue(c)));
Chris@159 513 paint.drawLine(5, 11 + y, cw - 5, 11 + y);
Chris@159 514 }
Chris@446 515
Chris@446 516 QString minstr = QString("%1").arg(min);
Chris@446 517 QString maxstr = QString("%1").arg(max);
Chris@446 518
Chris@446 519 paint.save();
Chris@446 520
Chris@446 521 QFont font = paint.font();
Chris@446 522 font.setPixelSize(10);
Chris@446 523 paint.setFont(font);
Chris@446 524
Chris@446 525 int msw = paint.fontMetrics().width(maxstr);
Chris@446 526
Chris@446 527 QMatrix m;
Chris@446 528 m.translate(cw - 6, ch + 10);
Chris@446 529 m.rotate(-90);
Chris@446 530
Chris@446 531 paint.setWorldMatrix(m);
Chris@446 532
Chris@446 533 v->drawVisibleText(paint, 2, 0, minstr, View::OutlinedText);
Chris@446 534
Chris@446 535 m.translate(ch - msw - 2, 0);
Chris@446 536 paint.setWorldMatrix(m);
Chris@446 537
Chris@446 538 v->drawVisibleText(paint, 0, 0, maxstr, View::OutlinedText);
Chris@446 539
Chris@446 540 paint.restore();
Chris@159 541 }
Chris@159 542
Chris@287 543 paint.setPen(v->getForeground());
Chris@159 544
Chris@445 545 int sh = m_model->getHeight();
Chris@445 546
Chris@445 547 int symin = m_miny;
Chris@445 548 int symax = m_maxy;
Chris@445 549 if (symax <= symin) {
Chris@445 550 symin = 0;
Chris@445 551 symax = sh;
Chris@445 552 }
Chris@445 553 if (symin < 0) symin = 0;
Chris@445 554 if (symax > sh) symax = sh;
Chris@445 555
Chris@98 556 int count = v->height() / paint.fontMetrics().height();
Chris@445 557 int step = (symax - symin) / count;
Chris@98 558 if (step == 0) step = 1;
Chris@25 559
Chris@445 560 float binHeight = float(v->height()) / (symax - symin);
Chris@445 561
Chris@445 562 for (size_t i = symin; i < symax; ++i) {
Chris@25 563
Chris@357 564 size_t idx = i;
Chris@357 565 if (m_invertVertical) idx = m_model->getHeight() - idx - 1;
Chris@357 566
Chris@357 567 if ((idx % step) != 0) continue;
Chris@98 568
Chris@445 569 int y0 = int(v->height() - ((i - symin) * binHeight) - 1);
Chris@25 570
Chris@357 571 QString text = m_model->getBinName(idx);
Chris@357 572 if (text == "") text = QString("[%1]").arg(idx + 1);
Chris@25 573
Chris@159 574 paint.drawLine(cw, y0, w, y0);
Chris@25 575
Chris@248 576 int cy = int(y0 - (step * binHeight)/2);
Chris@25 577 int ty = cy + paint.fontMetrics().ascent()/2;
Chris@25 578
Chris@159 579 paint.drawText(cw + 5, ty, text);
Chris@25 580 }
Chris@25 581 }
Chris@25 582
Chris@0 583 void
Chris@197 584 Colour3DPlotLayer::getColumn(size_t col,
Chris@197 585 DenseThreeDimensionalModel::Column &values) const
Chris@197 586 {
Chris@197 587 m_model->getColumn(col, values);
Chris@197 588
Chris@224 589 float colMax = 0.f, colMin = 0.f;
Chris@197 590
Chris@197 591 float min = 0.f, max = 0.f;
Chris@197 592 if (m_normalizeColumns) {
Chris@197 593 min = m_model->getMinimumLevel();
Chris@197 594 max = m_model->getMaximumLevel();
Chris@197 595 }
Chris@197 596
Chris@197 597 if (m_normalizeColumns) {
Chris@197 598 for (size_t y = 0; y < values.size(); ++y) {
Chris@224 599 if (y == 0 || values[y] > colMax) colMax = values[y];
Chris@224 600 if (y == 0 || values[y] < colMin) colMin = values[y];
Chris@197 601 }
Chris@224 602 if (colMin == colMax) colMax = colMin + 1;
Chris@197 603 }
Chris@197 604
Chris@197 605 for (size_t y = 0; y < values.size(); ++y) {
Chris@197 606
Chris@197 607 float value = min;
Chris@197 608
Chris@197 609 value = values[y];
Chris@197 610
Chris@197 611 if (m_normalizeColumns) {
Chris@224 612 float norm = (value - colMin) / (colMax - colMin);
Chris@224 613 value = min + (max - min) * norm;
Chris@197 614 }
Chris@197 615
Chris@197 616 values[y] = value;
Chris@197 617 }
Chris@197 618 }
Chris@197 619
Chris@197 620 void
Chris@197 621 Colour3DPlotLayer::fillCache(size_t firstBin, size_t lastBin) const
Chris@197 622 {
Chris@197 623 size_t modelStart = m_model->getStartFrame();
Chris@197 624 size_t modelEnd = m_model->getEndFrame();
Chris@197 625 size_t modelResolution = m_model->getResolution();
Chris@197 626
Chris@224 627 // std::cerr << "Colour3DPlotLayer::fillCache: " << firstBin << " -> " << lastBin << std::endl;
Chris@197 628
Chris@197 629 if (!m_normalizeVisibleArea || m_normalizeColumns) {
Chris@197 630 firstBin = modelStart / modelResolution;
Chris@197 631 lastBin = modelEnd / modelResolution;
Chris@197 632 }
Chris@197 633
Chris@197 634 size_t cacheWidth = lastBin - firstBin + 1;
Chris@197 635 size_t cacheHeight = m_model->getHeight();
Chris@197 636
Chris@197 637 if (m_cache &&
Chris@197 638 (m_cacheStart != firstBin ||
Chris@248 639 m_cache->width() != int(cacheWidth) ||
Chris@248 640 m_cache->height() != int(cacheHeight))) {
Chris@197 641
Chris@197 642 delete m_cache;
Chris@197 643 m_cache = 0;
Chris@197 644 }
Chris@197 645
Chris@197 646 if (m_cache) return;
Chris@197 647
Chris@197 648 m_cache = new QImage(cacheWidth, cacheHeight, QImage::Format_Indexed8);
Chris@197 649 m_cacheStart = firstBin;
Chris@197 650
Chris@224 651 // std::cerr << "Cache size " << cacheWidth << "x" << cacheHeight << " starting " << m_cacheStart << std::endl;
Chris@197 652
Chris@197 653 m_cache->setNumColors(256);
Chris@197 654 DenseThreeDimensionalModel::Column values;
Chris@197 655
Chris@197 656 float min = m_model->getMinimumLevel();
Chris@197 657 float max = m_model->getMaximumLevel();
Chris@197 658
Chris@197 659 if (m_colourScale == LogScale) {
Chris@197 660 LogRange::mapRange(min, max);
Chris@197 661 } else if (m_colourScale == PlusMinusOneScale) {
Chris@197 662 min = -1.f;
Chris@197 663 max = 1.f;
Chris@197 664 }
Chris@197 665
Chris@197 666 if (max == min) max = min + 1.0;
Chris@197 667
Chris@197 668 ColourMapper mapper(m_colourMap, 0.f, 255.f);
Chris@197 669
Chris@197 670 for (int index = 0; index < 256; ++index) {
Chris@197 671
Chris@197 672 QColor colour = mapper.map(index);
Chris@197 673 m_cache->setColor(index, qRgb(colour.red(), colour.green(), colour.blue()));
Chris@197 674 }
Chris@197 675
Chris@197 676 m_cache->fill(0);
Chris@197 677
Chris@224 678 float visibleMax = 0.f, visibleMin = 0.f;
Chris@197 679
Chris@197 680 if (m_normalizeVisibleArea && !m_normalizeColumns) {
Chris@197 681
Chris@197 682 for (size_t c = firstBin; c <= lastBin; ++c) {
Chris@197 683
Chris@197 684 values.clear();
Chris@197 685 getColumn(c, values);
Chris@197 686
Chris@224 687 float colMax = 0.f, colMin = 0.f;
Chris@197 688
Chris@197 689 for (size_t y = 0; y < m_model->getHeight(); ++y) {
Chris@197 690 if (y >= values.size()) break;
Chris@197 691 if (y == 0 || values[y] > colMax) colMax = values[y];
Chris@224 692 if (y == 0 || values[y] < colMin) colMin = values[y];
Chris@197 693 }
Chris@197 694
Chris@197 695 if (c == firstBin || colMax > visibleMax) visibleMax = colMax;
Chris@224 696 if (c == firstBin || colMin < visibleMin) visibleMin = colMin;
Chris@197 697 }
Chris@197 698 }
Chris@197 699
Chris@224 700 if (visibleMin == visibleMax) visibleMax = visibleMin + 1;
Chris@224 701
Chris@197 702 for (size_t c = firstBin; c <= lastBin; ++c) {
Chris@197 703
Chris@197 704 values.clear();
Chris@197 705 getColumn(c, values);
Chris@197 706
Chris@197 707 for (size_t y = 0; y < m_model->getHeight(); ++y) {
Chris@197 708
Chris@197 709 float value = min;
Chris@197 710 if (y < values.size()) {
Chris@197 711 value = values[y];
Chris@197 712 }
Chris@197 713
Chris@197 714 if (m_normalizeVisibleArea && !m_normalizeColumns) {
Chris@224 715 float norm = (value - visibleMin) / (visibleMax - visibleMin);
Chris@224 716 value = min + (max - min) * norm;
Chris@224 717 }
Chris@224 718
Chris@224 719 if (m_colourScale == LogScale) {
Chris@224 720 value = LogRange::map(value);
Chris@197 721 }
Chris@197 722
Chris@197 723 int pixel = int(((value - min) * 256) / (max - min));
Chris@197 724 if (pixel < 0) pixel = 0;
Chris@197 725 if (pixel > 255) pixel = 255;
Chris@197 726
Chris@357 727 if (m_invertVertical) {
Chris@357 728 m_cache->setPixel(c - firstBin, m_model->getHeight() - y - 1,
Chris@357 729 pixel);
Chris@357 730 } else {
Chris@357 731 m_cache->setPixel(c - firstBin, y, pixel);
Chris@357 732 }
Chris@197 733 }
Chris@197 734 }
Chris@197 735 }
Chris@197 736
Chris@197 737 void
Chris@44 738 Colour3DPlotLayer::paint(View *v, QPainter &paint, QRect rect) const
Chris@0 739 {
Chris@443 740 /*!!!
Chris@443 741 if (m_model) {
Chris@443 742 std::cerr << "Colour3DPlotLayer::paint: model says shouldUseLogValueScale = " << m_model->shouldUseLogValueScale() << std::endl;
Chris@443 743 }
Chris@443 744 */
Chris@0 745 // Profiler profiler("Colour3DPlotLayer::paint");
Chris@125 746 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@125 747 std::cerr << "Colour3DPlotLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << std::endl;
Chris@125 748 #endif
Chris@0 749
Chris@0 750 int completion = 0;
Chris@0 751 if (!m_model || !m_model->isOK() || !m_model->isReady(&completion)) {
Chris@0 752 if (completion > 0) {
Chris@44 753 paint.fillRect(0, 10, v->width() * completion / 100,
Chris@0 754 10, QColor(120, 120, 120));
Chris@0 755 }
Chris@0 756 return;
Chris@0 757 }
Chris@0 758
Chris@197 759 if (m_normalizeVisibleArea && !m_normalizeColumns) rect = v->rect();
Chris@197 760
Chris@0 761 size_t modelStart = m_model->getStartFrame();
Chris@0 762 size_t modelEnd = m_model->getEndFrame();
Chris@130 763 size_t modelResolution = m_model->getResolution();
Chris@0 764
Chris@197 765 // The cache is from the model's start frame to the model's end
Chris@197 766 // frame at the model's window increment frames per pixel. We
Chris@197 767 // want to draw from our start frame + x0 * zoomLevel to our start
Chris@197 768 // frame + x1 * zoomLevel at zoomLevel frames per pixel.
Chris@12 769
Chris@197 770 // We have quite different paint mechanisms for rendering "large"
Chris@197 771 // bins (more than one bin per pixel in both directions) and
Chris@197 772 // "small". This is "large"; see paintDense below for "small".
Chris@12 773
Chris@197 774 int x0 = rect.left();
Chris@197 775 int x1 = rect.right() + 1;
Chris@12 776
Chris@197 777 int h = v->height();
Chris@0 778
Chris@197 779 float srRatio =
Chris@197 780 float(v->getViewManager()->getMainModelSampleRate()) /
Chris@197 781 float(m_model->getSampleRate());
Chris@0 782
Chris@197 783 int sx0 = int((v->getFrameForX(x0) / srRatio - long(modelStart))
Chris@197 784 / long(modelResolution));
Chris@197 785 int sx1 = int((v->getFrameForX(x1) / srRatio - long(modelStart))
Chris@197 786 / long(modelResolution));
Chris@197 787 int sh = m_model->getHeight();
Chris@159 788
Chris@444 789 int symin = m_miny;
Chris@444 790 int symax = m_maxy;
Chris@444 791 if (symax <= symin) {
Chris@444 792 symin = 0;
Chris@444 793 symax = sh;
Chris@444 794 }
Chris@444 795 if (symin < 0) symin = 0;
Chris@444 796 if (symax > sh) symax = sh;
Chris@444 797
Chris@197 798 if (sx0 > 0) --sx0;
Chris@197 799 fillCache(sx0 < 0 ? 0 : sx0,
Chris@197 800 sx1 < 0 ? 0 : sx1);
Chris@0 801
Chris@351 802 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@351 803 std::cerr << "Colour3DPlotLayer::paint: height = "<< m_model->getHeight() << ", modelStart = " << modelStart << ", resolution = " << modelResolution << ", model rate = " << m_model->getSampleRate() << std::endl;
Chris@351 804 #endif
Chris@351 805
Chris@248 806 if (int(m_model->getHeight()) >= v->height() ||
Chris@348 807 int(modelResolution * m_model->getSampleRate()) < v->getZoomLevel() / 2) {
Chris@347 808 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@351 809 std::cerr << "calling paintDense" << std::endl;
Chris@347 810 #endif
Chris@98 811 paintDense(v, paint, rect);
Chris@98 812 return;
Chris@98 813 }
Chris@98 814
Chris@125 815 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@347 816 std::cerr << "Colour3DPlotLayer::paint: w " << x1-x0 << ", h " << h << ", sx0 " << sx0 << ", sx1 " << sx1 << ", sw " << sx1-sx0 << ", sh " << sh << std::endl;
Chris@130 817 std::cerr << "Colour3DPlotLayer: sample rate is " << m_model->getSampleRate() << ", resolution " << m_model->getResolution() << std::endl;
Chris@125 818 #endif
Chris@0 819
Chris@25 820 QPoint illuminatePos;
Chris@44 821 bool illuminate = v->shouldIlluminateLocalFeatures(this, illuminatePos);
Chris@54 822 char labelbuf[10];
Chris@25 823
Chris@197 824 for (int sx = sx0; sx <= sx1; ++sx) {
Chris@0 825
Chris@197 826 int scx = 0;
Chris@248 827 if (sx > int(m_cacheStart)) scx = sx - m_cacheStart;
Chris@197 828
Chris@130 829 int fx = sx * int(modelResolution);
Chris@0 830
Chris@351 831 if (fx + int(modelResolution) <= int(modelStart) ||
Chris@0 832 fx > int(modelEnd)) continue;
Chris@0 833
Chris@248 834 int rx0 = v->getXForFrame(int((fx + int(modelStart)) * srRatio));
Chris@248 835 int rx1 = v->getXForFrame(int((fx + int(modelStart) + int(modelResolution) + 1) * srRatio));
Chris@54 836
Chris@159 837 int rw = rx1 - rx0;
Chris@159 838 if (rw < 1) rw = 1;
Chris@54 839
Chris@159 840 bool showLabel = (rw > 10 &&
Chris@159 841 paint.fontMetrics().width("0.000000") < rw - 3 &&
Chris@54 842 paint.fontMetrics().height() < (h / sh));
Chris@98 843
Chris@444 844 for (int sy = symin; sy < symax; ++sy) {
Chris@0 845
Chris@444 846 int ry0 = h - ((sy - symin) * h) / (symax - symin) - 1;
Chris@0 847 QRgb pixel = qRgb(255, 255, 255);
Chris@197 848 if (scx >= 0 && scx < m_cache->width() &&
Chris@0 849 sy >= 0 && sy < m_cache->height()) {
Chris@197 850 pixel = m_cache->pixel(scx, sy);
Chris@0 851 }
Chris@0 852
Chris@444 853 QRect r(rx0, ry0 - h / (symax - symin) - 1,
Chris@444 854 rw, h / (symax - symin) + 1);
Chris@159 855
Chris@159 856 if (rw == 1) {
Chris@159 857 paint.setPen(pixel);
Chris@159 858 paint.setBrush(Qt::NoBrush);
Chris@159 859 paint.drawLine(r.x(), r.y(), r.x(), r.y() + r.height() - 1);
Chris@159 860 continue;
Chris@159 861 }
Chris@159 862
Chris@0 863 QColor pen(255, 255, 255, 80);
Chris@0 864 QColor brush(pixel);
Chris@159 865
Chris@159 866 if (rw > 3 && r.height() > 3) {
Chris@159 867 brush.setAlpha(160);
Chris@159 868 }
Chris@159 869
Chris@0 870 paint.setPen(Qt::NoPen);
Chris@0 871 paint.setBrush(brush);
Chris@0 872
Chris@25 873 if (illuminate) {
Chris@25 874 if (r.contains(illuminatePos)) {
Chris@287 875 paint.setPen(v->getForeground());
Chris@25 876 }
Chris@25 877 }
Chris@76 878
Chris@125 879 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@159 880 std::cerr << "rect " << r.x() << "," << r.y() << " "
Chris@159 881 << r.width() << "x" << r.height() << std::endl;
Chris@125 882 #endif
Chris@25 883
Chris@25 884 paint.drawRect(r);
Chris@0 885
Chris@54 886 if (showLabel) {
Chris@197 887 if (scx >= 0 && scx < m_cache->width() &&
Chris@54 888 sy >= 0 && sy < m_cache->height()) {
Chris@197 889 float value = m_model->getValueAt(scx, sy);
Chris@54 890 sprintf(labelbuf, "%06f", value);
Chris@54 891 QString text(labelbuf);
Chris@287 892 paint.setPen(v->getBackground());
Chris@54 893 paint.drawText(rx0 + 2,
Chris@54 894 ry0 - h / sh - 1 + 2 + paint.fontMetrics().ascent(),
Chris@54 895 text);
Chris@0 896 }
Chris@0 897 }
Chris@0 898 }
Chris@0 899 }
Chris@98 900 }
Chris@0 901
Chris@98 902 void
Chris@98 903 Colour3DPlotLayer::paintDense(View *v, QPainter &paint, QRect rect) const
Chris@98 904 {
Chris@98 905 size_t modelStart = m_model->getStartFrame();
Chris@130 906 size_t modelResolution = m_model->getResolution();
Chris@0 907
Chris@159 908 float srRatio =
Chris@159 909 float(v->getViewManager()->getMainModelSampleRate()) /
Chris@159 910 float(m_model->getSampleRate());
Chris@159 911
Chris@98 912 int x0 = rect.left();
Chris@98 913 int x1 = rect.right() + 1;
Chris@0 914
Chris@98 915 int w = x1 - x0;
Chris@98 916 int h = v->height();
Chris@160 917 int sh = m_model->getHeight();
Chris@98 918
Chris@444 919 int symin = m_miny;
Chris@444 920 int symax = m_maxy;
Chris@444 921 if (symax <= symin) {
Chris@444 922 symin = 0;
Chris@444 923 symax = sh;
Chris@444 924 }
Chris@444 925 if (symin < 0) symin = 0;
Chris@444 926 if (symax > sh) symax = sh;
Chris@444 927
Chris@98 928 QImage img(w, h, QImage::Format_RGB32);
Chris@98 929
Chris@98 930 for (int x = x0; x < x1; ++x) {
Chris@98 931
Chris@347 932 long xf = long(v->getFrameForX(x));
Chris@105 933 if (xf < 0) {
Chris@105 934 for (int y = 0; y < h; ++y) {
Chris@105 935 img.setPixel(x - x0, y, m_cache->color(0));
Chris@105 936 }
Chris@105 937 continue;
Chris@105 938 }
Chris@105 939
Chris@347 940 xf /= srRatio;
Chris@347 941
Chris@130 942 float sx0 = (float(xf) - modelStart) / modelResolution;
Chris@159 943 float sx1 = (float(v->getFrameForX(x+1) / srRatio) - modelStart) / modelResolution;
Chris@98 944
Chris@98 945 int sx0i = int(sx0 + 0.001);
Chris@98 946 int sx1i = int(sx1);
Chris@98 947
Chris@98 948 for (int y = 0; y < h; ++y) {
Chris@98 949
Chris@444 950 float sy0 = symin + (float(h - y - 1) * (symax - symin)) / h;
Chris@444 951 float sy1 = symin + (float(h - y) * (symax - symin)) / h;
Chris@98 952
Chris@98 953 int sy0i = int(sy0 + 0.001);
Chris@98 954 int sy1i = int(sy1);
Chris@98 955
Chris@98 956 float mag = 0.0, div = 0.0;
Chris@159 957 int max = 0;
Chris@98 958
Chris@98 959 for (int sx = sx0i; sx <= sx1i; ++sx) {
Chris@98 960
Chris@197 961 int scx = 0;
Chris@248 962 if (sx > int(m_cacheStart)) scx = sx - int(m_cacheStart);
Chris@197 963
Chris@197 964 if (scx < 0 || scx >= m_cache->width()) continue;
Chris@98 965
Chris@98 966 for (int sy = sy0i; sy <= sy1i; ++sy) {
Chris@98 967
Chris@98 968 if (sy < 0 || sy >= m_cache->height()) continue;
Chris@98 969
Chris@98 970 float prop = 1.0;
Chris@98 971 if (sx == sx0i) prop *= (sx + 1) - sx0;
Chris@98 972 if (sx == sx1i) prop *= sx1 - sx;
Chris@98 973 if (sy == sy0i) prop *= (sy + 1) - sy0;
Chris@98 974 if (sy == sy1i) prop *= sy1 - sy;
Chris@98 975
Chris@197 976 mag += prop * m_cache->pixelIndex(scx, sy);
Chris@197 977 max = std::max(max, m_cache->pixelIndex(scx, sy));
Chris@98 978 div += prop;
Chris@98 979 }
Chris@98 980 }
Chris@98 981
Chris@98 982 if (div != 0) mag /= div;
Chris@98 983 if (mag < 0) mag = 0;
Chris@98 984 if (mag > 255) mag = 255;
Chris@159 985 if (max < 0) max = 0;
Chris@159 986 if (max > 255) max = 255;
Chris@98 987
Chris@98 988 img.setPixel(x - x0, y, m_cache->color(int(mag + 0.001)));
Chris@98 989 }
Chris@0 990 }
Chris@0 991
Chris@98 992 paint.drawImage(x0, 0, img);
Chris@0 993 }
Chris@0 994
Chris@28 995 bool
Chris@44 996 Colour3DPlotLayer::snapToFeatureFrame(View *v, int &frame,
Chris@28 997 size_t &resolution,
Chris@28 998 SnapType snap) const
Chris@24 999 {
Chris@24 1000 if (!m_model) {
Chris@44 1001 return Layer::snapToFeatureFrame(v, frame, resolution, snap);
Chris@24 1002 }
Chris@24 1003
Chris@130 1004 resolution = m_model->getResolution();
Chris@28 1005 int left = (frame / resolution) * resolution;
Chris@28 1006 int right = left + resolution;
Chris@28 1007
Chris@28 1008 switch (snap) {
Chris@28 1009 case SnapLeft: frame = left; break;
Chris@28 1010 case SnapRight: frame = right; break;
Chris@28 1011 case SnapNearest:
Chris@28 1012 case SnapNeighbouring:
Chris@28 1013 if (frame - left > right - frame) frame = right;
Chris@28 1014 else frame = left;
Chris@28 1015 break;
Chris@28 1016 }
Chris@24 1017
Chris@28 1018 return true;
Chris@24 1019 }
Chris@24 1020
Chris@316 1021 void
Chris@316 1022 Colour3DPlotLayer::toXml(QTextStream &stream,
Chris@316 1023 QString indent, QString extraAttributes) const
Chris@197 1024 {
Chris@316 1025 QString s = QString("scale=\"%1\" "
Chris@316 1026 "colourScheme=\"%2\" "
Chris@316 1027 "normalizeColumns=\"%3\" "
Chris@445 1028 "normalizeVisibleArea=\"%4\" "
Chris@445 1029 "minY=\"%5\" "
Chris@445 1030 "maxY=\"%6\" ")
Chris@197 1031 .arg((int)m_colourScale)
Chris@197 1032 .arg(m_colourMap)
Chris@197 1033 .arg(m_normalizeColumns ? "true" : "false")
Chris@445 1034 .arg(m_normalizeVisibleArea ? "true" : "false")
Chris@445 1035 .arg(m_miny)
Chris@445 1036 .arg(m_maxy);
Chris@197 1037
Chris@316 1038 Layer::toXml(stream, indent, extraAttributes + " " + s);
Chris@197 1039 }
Chris@197 1040
Chris@197 1041 void
Chris@197 1042 Colour3DPlotLayer::setProperties(const QXmlAttributes &attributes)
Chris@197 1043 {
Chris@445 1044 bool ok = false, alsoOk = false;
Chris@197 1045
Chris@197 1046 ColourScale scale = (ColourScale)attributes.value("scale").toInt(&ok);
Chris@197 1047 if (ok) setColourScale(scale);
Chris@197 1048
Chris@197 1049 int colourMap = attributes.value("colourScheme").toInt(&ok);
Chris@197 1050 if (ok) setColourMap(colourMap);
Chris@197 1051
Chris@197 1052 bool normalizeColumns =
Chris@197 1053 (attributes.value("normalizeColumns").trimmed() == "true");
Chris@197 1054 setNormalizeColumns(normalizeColumns);
Chris@197 1055
Chris@197 1056 bool normalizeVisibleArea =
Chris@197 1057 (attributes.value("normalizeVisibleArea").trimmed() == "true");
Chris@197 1058 setNormalizeVisibleArea(normalizeVisibleArea);
Chris@445 1059
Chris@445 1060 float min = attributes.value("minY").toFloat(&ok);
Chris@445 1061 float max = attributes.value("maxY").toFloat(&alsoOk);
Chris@445 1062 if (ok && alsoOk) setDisplayExtents(min, max);
Chris@197 1063 }
Chris@197 1064