comparison layer/Colour3DPlotLayer.cpp @ 1148:c0d841cb8ab9 tony-2.0-integration

Merge latest SV 3.0 branch code
author Chris Cannam
date Fri, 19 Aug 2016 15:58:57 +0100
parents 4e7ed3252d80
children 0edfed2c8482
comparison
equal deleted inserted replaced
1009:96cf499fad62 1148:c0d841cb8ab9
13 COPYING included with this distribution for more information. 13 COPYING included with this distribution for more information.
14 */ 14 */
15 15
16 #include "Colour3DPlotLayer.h" 16 #include "Colour3DPlotLayer.h"
17 17
18 #include "view/View.h"
19 #include "base/Profiler.h" 18 #include "base/Profiler.h"
20 #include "base/LogRange.h" 19 #include "base/LogRange.h"
21 #include "base/RangeMapper.h" 20 #include "base/RangeMapper.h"
21
22 #include "ColourMapper.h" 22 #include "ColourMapper.h"
23 #include "LayerGeometryProvider.h"
24 #include "PaintAssistant.h"
25
26 #include "data/model/Dense3DModelPeakCache.h"
27
28 #include "view/ViewManager.h"
23 29
24 #include <QPainter> 30 #include <QPainter>
25 #include <QImage> 31 #include <QImage>
26 #include <QRect> 32 #include <QRect>
27 #include <QTextStream> 33 #include <QTextStream>
34 #include <QSettings>
28 35
29 #include <iostream> 36 #include <iostream>
30 37
31 #include <cassert> 38 #include <cassert>
32 39
39 //#define DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1 46 //#define DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1
40 47
41 48
42 Colour3DPlotLayer::Colour3DPlotLayer() : 49 Colour3DPlotLayer::Colour3DPlotLayer() :
43 m_model(0), 50 m_model(0),
44 m_cache(0), 51 m_colourScale(ColourScaleType::Linear),
45 m_peaksCache(0),
46 m_cacheValidStart(0),
47 m_cacheValidEnd(0),
48 m_colourScale(LinearScale),
49 m_colourScaleSet(false), 52 m_colourScaleSet(false),
50 m_colourMap(0), 53 m_colourMap(0),
51 m_gain(1.0), 54 m_gain(1.0),
52 m_binScale(LinearBinScale), 55 m_binScale(BinScale::Linear),
53 m_normalizeColumns(false), 56 m_normalization(ColumnNormalization::None),
54 m_normalizeVisibleArea(false), 57 m_normalizeVisibleArea(false),
55 m_normalizeHybrid(false),
56 m_invertVertical(false), 58 m_invertVertical(false),
57 m_rectified(false),
58 m_opaque(false), 59 m_opaque(false),
59 m_smooth(false), 60 m_smooth(false),
60 m_peakResolution(256), 61 m_peakResolution(256),
61 m_miny(0), 62 m_miny(0),
62 m_maxy(0) 63 m_maxy(0),
63 { 64 m_synchronous(false),
64 65 m_peakCache(0),
66 m_peakCacheDivisor(8)
67 {
68 QSettings settings;
69 settings.beginGroup("Preferences");
70 setColourMap(settings.value("colour-3d-plot-colour", ColourMapper::Green).toInt());
71 settings.endGroup();
65 } 72 }
66 73
67 Colour3DPlotLayer::~Colour3DPlotLayer() 74 Colour3DPlotLayer::~Colour3DPlotLayer()
68 { 75 {
69 delete m_cache; 76 invalidateRenderers();
70 delete m_peaksCache; 77 delete m_peakCache;
78 }
79
80 ColourScaleType
81 Colour3DPlotLayer::convertToColourScale(int value)
82 {
83 switch (value) {
84 default:
85 case 0: return ColourScaleType::Linear;
86 case 1: return ColourScaleType::Log;
87 case 2: return ColourScaleType::PlusMinusOne;
88 case 3: return ColourScaleType::Absolute;
89 }
90 }
91
92 int
93 Colour3DPlotLayer::convertFromColourScale(ColourScaleType scale)
94 {
95 switch (scale) {
96 case ColourScaleType::Linear: return 0;
97 case ColourScaleType::Log: return 1;
98 case ColourScaleType::PlusMinusOne: return 2;
99 case ColourScaleType::Absolute: return 3;
100
101 case ColourScaleType::Meter:
102 case ColourScaleType::Phase:
103 default: return 0;
104 }
105 }
106
107 std::pair<ColumnNormalization, bool>
108 Colour3DPlotLayer::convertToColumnNorm(int value)
109 {
110 switch (value) {
111 default:
112 case 0: return { ColumnNormalization::None, false };
113 case 1: return { ColumnNormalization::Max1, false };
114 case 2: return { ColumnNormalization::None, true }; // visible area
115 case 3: return { ColumnNormalization::Hybrid, false };
116 }
117 }
118
119 int
120 Colour3DPlotLayer::convertFromColumnNorm(ColumnNormalization norm, bool visible)
121 {
122 if (visible) return 2;
123 switch (norm) {
124 case ColumnNormalization::None: return 0;
125 case ColumnNormalization::Max1: return 1;
126 case ColumnNormalization::Hybrid: return 3;
127
128 case ColumnNormalization::Sum1:
129 default: return 0;
130 }
131 }
132
133 void
134 Colour3DPlotLayer::setSynchronousPainting(bool synchronous)
135 {
136 m_synchronous = synchronous;
71 } 137 }
72 138
73 void 139 void
74 Colour3DPlotLayer::setModel(const DenseThreeDimensionalModel *model) 140 Colour3DPlotLayer::setModel(const DenseThreeDimensionalModel *model)
75 { 141 {
90 } else if (model->getResolution() > 128) { 156 } else if (model->getResolution() > 128) {
91 m_peakResolution = 64; 157 m_peakResolution = 64;
92 } else if (model->getResolution() > 2) { 158 } else if (model->getResolution() > 2) {
93 m_peakResolution = 128; 159 m_peakResolution = 128;
94 } 160 }
95 cacheInvalid(); 161
162 delete m_peakCache;
163 m_peakCache = 0;
164
165 invalidateRenderers();
96 166
97 emit modelReplaced(); 167 emit modelReplaced();
98 emit sliceableModelReplaced(oldModel, model); 168 emit sliceableModelReplaced(oldModel, model);
99 } 169 }
100 170
101 void 171 void
102 Colour3DPlotLayer::cacheInvalid() 172 Colour3DPlotLayer::cacheInvalid()
103 { 173 {
104 delete m_cache; 174 invalidateRenderers();
105 delete m_peaksCache; 175 }
106 m_cache = 0; 176
107 m_peaksCache = 0; 177 void
108 m_cacheValidStart = 0; 178 Colour3DPlotLayer::cacheInvalid(sv_frame_t /* startFrame */,
109 m_cacheValidEnd = 0; 179 sv_frame_t /* endFrame */)
110 } 180 {
111 181 //!!! should do this only if the range is visible
112 void 182 delete m_peakCache;
113 Colour3DPlotLayer::cacheInvalid(sv_frame_t startFrame, sv_frame_t endFrame) 183 m_peakCache = 0;
114 { 184
115 if (!m_cache || !m_model) return; 185 invalidateRenderers();
116 186 }
117 int modelResolution = m_model->getResolution(); 187
118 int start = int(startFrame / modelResolution); 188 void
119 int end = int(endFrame / modelResolution + 1); 189 Colour3DPlotLayer::invalidateRenderers()
120 if (m_cacheValidStart < end) m_cacheValidStart = end; 190 {
121 if (m_cacheValidEnd > start) m_cacheValidEnd = start; 191 for (ViewRendererMap::iterator i = m_renderers.begin();
122 if (m_cacheValidStart > m_cacheValidEnd) m_cacheValidEnd = m_cacheValidStart; 192 i != m_renderers.end(); ++i) {
193 delete i->second;
194 }
195 m_renderers.clear();
196 }
197
198 Dense3DModelPeakCache *
199 Colour3DPlotLayer::getPeakCache() const
200 {
201 if (!m_peakCache) {
202 m_peakCache = new Dense3DModelPeakCache(m_model, m_peakCacheDivisor);
203 }
204 return m_peakCache;
123 } 205 }
124 206
125 void 207 void
126 Colour3DPlotLayer::modelChanged() 208 Colour3DPlotLayer::modelChanged()
127 { 209 {
128 if (!m_colourScaleSet && m_colourScale == LinearScale) { 210 if (!m_colourScaleSet && m_colourScale == ColourScaleType::Linear) {
129 if (m_model) { 211 if (m_model) {
130 if (m_model->shouldUseLogValueScale()) { 212 if (m_model->shouldUseLogValueScale()) {
131 setColourScale(LogScale); 213 setColourScale(ColourScaleType::Log);
132 } else { 214 } else {
133 m_colourScaleSet = true; 215 m_colourScaleSet = true;
134 } 216 }
135 } 217 }
136 } 218 }
138 } 220 }
139 221
140 void 222 void
141 Colour3DPlotLayer::modelChangedWithin(sv_frame_t startFrame, sv_frame_t endFrame) 223 Colour3DPlotLayer::modelChangedWithin(sv_frame_t startFrame, sv_frame_t endFrame)
142 { 224 {
143 if (!m_colourScaleSet && m_colourScale == LinearScale) { 225 if (!m_colourScaleSet && m_colourScale == ColourScaleType::Linear) {
144 if (m_model && m_model->getWidth() > 50) { 226 if (m_model && m_model->getWidth() > 50) {
145 if (m_model->shouldUseLogValueScale()) { 227 if (m_model->shouldUseLogValueScale()) {
146 setColourScale(LogScale); 228 setColourScale(ColourScaleType::Log);
147 } else { 229 } else {
148 m_colourScaleSet = true; 230 m_colourScaleSet = true;
149 } 231 }
150 } 232 }
151 } 233 }
156 Colour3DPlotLayer::getProperties() const 238 Colour3DPlotLayer::getProperties() const
157 { 239 {
158 PropertyList list; 240 PropertyList list;
159 list.push_back("Colour"); 241 list.push_back("Colour");
160 list.push_back("Colour Scale"); 242 list.push_back("Colour Scale");
161 list.push_back("Normalize Columns"); 243 list.push_back("Normalization");
162 list.push_back("Normalize Visible Area");
163 list.push_back("Gain"); 244 list.push_back("Gain");
164 list.push_back("Bin Scale"); 245 list.push_back("Bin Scale");
165 list.push_back("Invert Vertical Scale"); 246 list.push_back("Invert Vertical Scale");
166 list.push_back("Show Rectified");
167 list.push_back("Opaque"); 247 list.push_back("Opaque");
168 list.push_back("Smooth"); 248 list.push_back("Smooth");
169 return list; 249 return list;
170 } 250 }
171 251
172 QString 252 QString
173 Colour3DPlotLayer::getPropertyLabel(const PropertyName &name) const 253 Colour3DPlotLayer::getPropertyLabel(const PropertyName &name) const
174 { 254 {
175 if (name == "Colour") return tr("Colour"); 255 if (name == "Colour") return tr("Colour");
176 if (name == "Colour Scale") return tr("Scale"); 256 if (name == "Colour Scale") return tr("Scale");
177 if (name == "Normalize Columns") return tr("Normalize Columns"); 257 if (name == "Normalization") return tr("Normalization");
178 if (name == "Normalize Visible Area") return tr("Normalize Visible Area");
179 if (name == "Invert Vertical Scale") return tr("Invert Vertical Scale"); 258 if (name == "Invert Vertical Scale") return tr("Invert Vertical Scale");
180 if (name == "Show Rectified") return tr("Half-Wave Rectify");
181 if (name == "Gain") return tr("Gain"); 259 if (name == "Gain") return tr("Gain");
182 if (name == "Opaque") return tr("Always Opaque"); 260 if (name == "Opaque") return tr("Always Opaque");
183 if (name == "Smooth") return tr("Smooth"); 261 if (name == "Smooth") return tr("Smooth");
184 if (name == "Bin Scale") return tr("Bin Scale"); 262 if (name == "Bin Scale") return tr("Bin Scale");
185 return ""; 263 return "";
186 } 264 }
187 265
188 QString 266 QString
189 Colour3DPlotLayer::getPropertyIconName(const PropertyName &name) const 267 Colour3DPlotLayer::getPropertyIconName(const PropertyName &name) const
190 { 268 {
191 if (name == "Normalize Columns") return "normalise-columns";
192 if (name == "Normalize Visible Area") return "normalise";
193 if (name == "Invert Vertical Scale") return "invert-vertical"; 269 if (name == "Invert Vertical Scale") return "invert-vertical";
194 if (name == "Show Rectified") return "derivative";
195 if (name == "Opaque") return "opaque"; 270 if (name == "Opaque") return "opaque";
196 if (name == "Smooth") return "smooth"; 271 if (name == "Smooth") return "smooth";
197 return ""; 272 return "";
198 } 273 }
199 274
200 Layer::PropertyType 275 Layer::PropertyType
201 Colour3DPlotLayer::getPropertyType(const PropertyName &name) const 276 Colour3DPlotLayer::getPropertyType(const PropertyName &name) const
202 { 277 {
203 if (name == "Gain") return RangeProperty; 278 if (name == "Gain") return RangeProperty;
204 if (name == "Normalize Columns") return ToggleProperty;
205 if (name == "Normalize Visible Area") return ToggleProperty;
206 if (name == "Invert Vertical Scale") return ToggleProperty; 279 if (name == "Invert Vertical Scale") return ToggleProperty;
207 if (name == "Show Rectified") return ToggleProperty;
208 if (name == "Opaque") return ToggleProperty; 280 if (name == "Opaque") return ToggleProperty;
209 if (name == "Smooth") return ToggleProperty; 281 if (name == "Smooth") return ToggleProperty;
210 return ValueProperty; 282 return ValueProperty;
211 } 283 }
212 284
213 QString 285 QString
214 Colour3DPlotLayer::getPropertyGroupName(const PropertyName &name) const 286 Colour3DPlotLayer::getPropertyGroupName(const PropertyName &name) const
215 { 287 {
216 if (name == "Normalize Columns" || 288 if (name == "Normalization" ||
217 name == "Normalize Visible Area" || 289 name == "Colour Scale" ||
218 name == "Colour Scale" ||
219 name == "Show Rectified" ||
220 name == "Gain") return tr("Scale"); 290 name == "Gain") return tr("Scale");
221 if (name == "Bin Scale" || 291 if (name == "Bin Scale" ||
222 name == "Invert Vertical Scale") return tr("Bins"); 292 name == "Invert Vertical Scale") return tr("Bins");
223 if (name == "Opaque" || 293 if (name == "Opaque" ||
224 name == "Smooth" || 294 name == "Smooth" ||
250 if (val < *min) val = *min; 320 if (val < *min) val = *min;
251 if (val > *max) val = *max; 321 if (val > *max) val = *max;
252 322
253 } else if (name == "Colour Scale") { 323 } else if (name == "Colour Scale") {
254 324
325 // linear, log, +/-1, abs
255 *min = 0; 326 *min = 0;
256 *max = 3; 327 *max = 3;
257 *deflt = (int)LinearScale; 328 *deflt = 0;
258 329
259 val = (int)m_colourScale; 330 val = convertFromColourScale(m_colourScale);
260 331
261 } else if (name == "Colour") { 332 } else if (name == "Colour") {
262 333
263 *min = 0; 334 *min = 0;
264 *max = ColourMapper::getColourMapCount() - 1; 335 *max = ColourMapper::getColourMapCount() - 1;
265 *deflt = 0; 336 *deflt = 0;
266 337
267 val = m_colourMap; 338 val = m_colourMap;
268 339
269 } else if (name == "Normalize Columns") { 340 } else if (name == "Normalization") {
270 341
342 *min = 0;
343 *max = 3;
271 *deflt = 0; 344 *deflt = 0;
272 val = (m_normalizeColumns ? 1 : 0); 345
273 346 val = convertFromColumnNorm(m_normalization, m_normalizeVisibleArea);
274 } else if (name == "Normalize Visible Area") {
275
276 *deflt = 0;
277 val = (m_normalizeVisibleArea ? 1 : 0);
278 347
279 } else if (name == "Invert Vertical Scale") { 348 } else if (name == "Invert Vertical Scale") {
280 349
281 *deflt = 0; 350 *deflt = 0;
282 val = (m_invertVertical ? 1 : 0); 351 val = (m_invertVertical ? 1 : 0);
283 352
284 } else if (name == "Show Rectified") {
285
286 if (min) *min = 0;
287 if (max) *max = 0;
288 if (deflt) *deflt = 0;
289 val = (m_rectified ? 1.0 : 0.0);
290
291 } else if (name == "Bin Scale") { 353 } else if (name == "Bin Scale") {
292 354
293 *min = 0; 355 *min = 0;
294 *max = 1; 356 *max = 1;
295 *deflt = int(LinearBinScale); 357 *deflt = int(BinScale::Linear);
296 val = (int)m_binScale; 358 val = (int)m_binScale;
297 359
298 } else if (name == "Opaque") { 360 } else if (name == "Opaque") {
299 361
300 *deflt = 0; 362 *deflt = 0;
326 case 1: return tr("Log"); 388 case 1: return tr("Log");
327 case 2: return tr("+/-1"); 389 case 2: return tr("+/-1");
328 case 3: return tr("Absolute"); 390 case 3: return tr("Absolute");
329 } 391 }
330 } 392 }
393 if (name == "Normalization") {
394 return ""; // icon only
395 }
331 if (name == "Bin Scale") { 396 if (name == "Bin Scale") {
332 switch (value) { 397 switch (value) {
333 default: 398 default:
334 case 0: return tr("Linear"); 399 case 0: return tr("Linear");
335 case 1: return tr("Log"); 400 case 1: return tr("Log");
336 } 401 }
337 } 402 }
338 return tr("<unknown>"); 403 return tr("<unknown>");
339 } 404 }
340 405
406 QString
407 Colour3DPlotLayer::getPropertyValueIconName(const PropertyName &name,
408 int value) const
409 {
410 if (name == "Normalization") {
411 switch(value) {
412 default:
413 case 0: return "normalise-none";
414 case 1: return "normalise-columns";
415 case 2: return "normalise";
416 case 3: return "normalise-hybrid";
417 }
418 }
419 return "";
420 }
421
341 RangeMapper * 422 RangeMapper *
342 Colour3DPlotLayer::getNewPropertyRangeMapper(const PropertyName &name) const 423 Colour3DPlotLayer::getNewPropertyRangeMapper(const PropertyName &name) const
343 { 424 {
344 if (name == "Gain") { 425 if (name == "Gain") {
345 return new LinearRangeMapper(-50, 50, -25, 25, tr("dB")); 426 return new LinearRangeMapper(-50, 50, -25, 25, tr("dB"));
351 Colour3DPlotLayer::setProperty(const PropertyName &name, int value) 432 Colour3DPlotLayer::setProperty(const PropertyName &name, int value)
352 { 433 {
353 if (name == "Gain") { 434 if (name == "Gain") {
354 setGain(float(pow(10, value/20.0))); 435 setGain(float(pow(10, value/20.0)));
355 } else if (name == "Colour Scale") { 436 } else if (name == "Colour Scale") {
356 switch (value) { 437 setColourScale(convertToColourScale(value));
357 default:
358 case 0: setColourScale(LinearScale); break;
359 case 1: setColourScale(LogScale); break;
360 case 2: setColourScale(PlusMinusOneScale); break;
361 case 3: setColourScale(AbsoluteScale); break;
362 }
363 } else if (name == "Colour") { 438 } else if (name == "Colour") {
364 setColourMap(value); 439 setColourMap(value);
365 } else if (name == "Normalize Columns") {
366 setNormalizeColumns(value ? true : false);
367 } else if (name == "Normalize Visible Area") {
368 setNormalizeVisibleArea(value ? true : false);
369 } else if (name == "Invert Vertical Scale") { 440 } else if (name == "Invert Vertical Scale") {
370 setInvertVertical(value ? true : false); 441 setInvertVertical(value ? true : false);
371 } else if (name == "Show Rectified") {
372 setShowRectified(value > 0.5);
373 } else if (name == "Opaque") { 442 } else if (name == "Opaque") {
374 setOpaque(value ? true : false); 443 setOpaque(value ? true : false);
375 } else if (name == "Smooth") { 444 } else if (name == "Smooth") {
376 setSmooth(value ? true : false); 445 setSmooth(value ? true : false);
377 } else if (name == "Bin Scale") { 446 } else if (name == "Bin Scale") {
378 switch (value) { 447 switch (value) {
379 default: 448 default:
380 case 0: setBinScale(LinearBinScale); break; 449 case 0: setBinScale(BinScale::Linear); break;
381 case 1: setBinScale(LogBinScale); break; 450 case 1: setBinScale(BinScale::Log); break;
382 } 451 }
383 } 452 } else if (name == "Normalization") {
384 } 453 auto n = convertToColumnNorm(value);
385 454 setNormalization(n.first);
386 void 455 setNormalizeVisibleArea(n.second);
387 Colour3DPlotLayer::setColourScale(ColourScale scale) 456 }
457 }
458
459 void
460 Colour3DPlotLayer::setColourScale(ColourScaleType scale)
388 { 461 {
389 if (m_colourScale == scale) return; 462 if (m_colourScale == scale) return;
390 m_colourScale = scale; 463 m_colourScale = scale;
391 m_colourScaleSet = true; 464 m_colourScaleSet = true;
392 cacheInvalid(); 465 invalidateRenderers();
393 emit layerParametersChanged(); 466 emit layerParametersChanged();
394 } 467 }
395 468
396 void 469 void
397 Colour3DPlotLayer::setColourMap(int map) 470 Colour3DPlotLayer::setColourMap(int map)
398 { 471 {
399 if (m_colourMap == map) return; 472 if (m_colourMap == map) return;
400 m_colourMap = map; 473 m_colourMap = map;
401 cacheInvalid(); 474 invalidateRenderers();
402 emit layerParametersChanged(); 475 emit layerParametersChanged();
403 } 476 }
404 477
405 void 478 void
406 Colour3DPlotLayer::setGain(float gain) 479 Colour3DPlotLayer::setGain(float gain)
407 { 480 {
408 if (m_gain == gain) return; 481 if (m_gain == gain) return;
409 m_gain = gain; 482 m_gain = gain;
410 cacheInvalid(); 483 invalidateRenderers();
411 emit layerParametersChanged(); 484 emit layerParametersChanged();
412 } 485 }
413 486
414 float 487 float
415 Colour3DPlotLayer::getGain() const 488 Colour3DPlotLayer::getGain() const
420 void 493 void
421 Colour3DPlotLayer::setBinScale(BinScale binScale) 494 Colour3DPlotLayer::setBinScale(BinScale binScale)
422 { 495 {
423 if (m_binScale == binScale) return; 496 if (m_binScale == binScale) return;
424 m_binScale = binScale; 497 m_binScale = binScale;
425 cacheInvalid(); 498 invalidateRenderers();
426 emit layerParametersChanged(); 499 emit layerParametersChanged();
427 } 500 }
428 501
429 Colour3DPlotLayer::BinScale 502 BinScale
430 Colour3DPlotLayer::getBinScale() const 503 Colour3DPlotLayer::getBinScale() const
431 { 504 {
432 return m_binScale; 505 return m_binScale;
433 } 506 }
434 507
435 void 508 void
436 Colour3DPlotLayer::setNormalizeColumns(bool n) 509 Colour3DPlotLayer::setNormalization(ColumnNormalization n)
437 { 510 {
438 if (m_normalizeColumns == n) return; 511 if (m_normalization == n) return;
439 m_normalizeColumns = n; 512
440 cacheInvalid(); 513 m_normalization = n;
514 invalidateRenderers();
515
441 emit layerParametersChanged(); 516 emit layerParametersChanged();
442 } 517 }
443 518
444 bool 519 ColumnNormalization
445 Colour3DPlotLayer::getNormalizeColumns() const 520 Colour3DPlotLayer::getNormalization() const
446 { 521 {
447 return m_normalizeColumns; 522 return m_normalization;
448 }
449
450 void
451 Colour3DPlotLayer::setNormalizeHybrid(bool n)
452 {
453 if (m_normalizeHybrid == n) return;
454 m_normalizeHybrid = n;
455 cacheInvalid();
456 emit layerParametersChanged();
457 }
458
459 bool
460 Colour3DPlotLayer::getNormalizeHybrid() const
461 {
462 return m_normalizeHybrid;
463 } 523 }
464 524
465 void 525 void
466 Colour3DPlotLayer::setNormalizeVisibleArea(bool n) 526 Colour3DPlotLayer::setNormalizeVisibleArea(bool n)
467 { 527 {
468 if (m_normalizeVisibleArea == n) return; 528 if (m_normalizeVisibleArea == n) return;
529
469 m_normalizeVisibleArea = n; 530 m_normalizeVisibleArea = n;
470 cacheInvalid(); 531 invalidateRenderers();
532
471 emit layerParametersChanged(); 533 emit layerParametersChanged();
472 } 534 }
473 535
474 bool 536 bool
475 Colour3DPlotLayer::getNormalizeVisibleArea() const 537 Colour3DPlotLayer::getNormalizeVisibleArea() const
480 void 542 void
481 Colour3DPlotLayer::setInvertVertical(bool n) 543 Colour3DPlotLayer::setInvertVertical(bool n)
482 { 544 {
483 if (m_invertVertical == n) return; 545 if (m_invertVertical == n) return;
484 m_invertVertical = n; 546 m_invertVertical = n;
485 cacheInvalid(); 547 invalidateRenderers();
486 emit layerParametersChanged();
487 }
488
489 void
490 Colour3DPlotLayer::setShowRectified(bool show)
491 {
492 if (m_rectified == show) return;
493 m_rectified = show;
494 cacheInvalid();
495 emit layerParametersChanged(); 548 emit layerParametersChanged();
496 } 549 }
497 550
498 void 551 void
499 Colour3DPlotLayer::setOpaque(bool n) 552 Colour3DPlotLayer::setOpaque(bool n)
500 { 553 {
501 if (m_opaque == n) return; 554 if (m_opaque == n) return;
502 m_opaque = n; 555 m_opaque = n;
556 invalidateRenderers();
503 emit layerParametersChanged(); 557 emit layerParametersChanged();
504 } 558 }
505 559
506 void 560 void
507 Colour3DPlotLayer::setSmooth(bool n) 561 Colour3DPlotLayer::setSmooth(bool n)
508 { 562 {
509 if (m_smooth == n) return; 563 if (m_smooth == n) return;
510 m_smooth = n; 564 m_smooth = n;
565 invalidateRenderers();
511 emit layerParametersChanged(); 566 emit layerParametersChanged();
512 } 567 }
513 568
514 bool 569 bool
515 Colour3DPlotLayer::getInvertVertical() const 570 Colour3DPlotLayer::getInvertVertical() const
552 Layer::setLayerDormant(v, false); 607 Layer::setLayerDormant(v, false);
553 } 608 }
554 } 609 }
555 610
556 bool 611 bool
557 Colour3DPlotLayer::isLayerScrollable(const LayerGeometryProvider *v) const 612 Colour3DPlotLayer::isLayerScrollable(const LayerGeometryProvider */* v */) const
558 { 613 {
559 if (m_normalizeVisibleArea) { 614 if (m_normalizeVisibleArea) {
560 return false; 615 return false;
561 } 616 }
562 if (shouldPaintDenseIn(v)) { 617 //!!! ah hang on, if we're potentially rendering incrementally
563 return true; 618 //!!! they we can't be scrollable
564 } 619 return false;
565 QPoint discard; 620 // if (getRenderer(v)->willRenderOpaque(v)) {
566 return !v->shouldIlluminateLocalFeatures(this, discard); 621 // return true;
622 // }
623 // QPoint discard;
624 // return !v->shouldIlluminateLocalFeatures(this, discard);
567 } 625 }
568 626
569 bool 627 bool
570 Colour3DPlotLayer::getValueExtents(double &min, double &max, 628 Colour3DPlotLayer::getValueExtents(double &min, double &max,
571 bool &logarithmic, QString &unit) const 629 bool &logarithmic, QString &unit) const
605 { 663 {
606 if (!m_model) return false; 664 if (!m_model) return false;
607 665
608 m_miny = int(lrint(min)); 666 m_miny = int(lrint(min));
609 m_maxy = int(lrint(max)); 667 m_maxy = int(lrint(max));
668
669 invalidateRenderers();
610 670
611 emit layerParametersChanged(); 671 emit layerParametersChanged();
612 return true; 672 return true;
613 } 673 }
614 674
652 m_miny = int(lrint(centre - dist/2.0)); 712 m_miny = int(lrint(centre - dist/2.0));
653 if (m_miny < 0) m_miny = 0; 713 if (m_miny < 0) m_miny = 0;
654 m_maxy = m_miny + dist; 714 m_maxy = m_miny + dist;
655 if (m_maxy > m_model->getHeight()) m_maxy = m_model->getHeight(); 715 if (m_maxy > m_model->getHeight()) m_maxy = m_model->getHeight();
656 716
717 invalidateRenderers();
718
657 // SVDEBUG << "Colour3DPlotLayer::setVerticalZoomStep(" <<step <<"): after: miny = " << m_miny << ", maxy = " << m_maxy << endl; 719 // SVDEBUG << "Colour3DPlotLayer::setVerticalZoomStep(" <<step <<"): after: miny = " << m_miny << ", maxy = " << m_maxy << endl;
658 720
659 emit layerParametersChanged(); 721 emit layerParametersChanged();
660 } 722 }
661 723
667 return new LinearRangeMapper(0, m_model->getHeight(), 729 return new LinearRangeMapper(0, m_model->getHeight(),
668 0, m_model->getHeight(), ""); 730 0, m_model->getHeight(), "");
669 } 731 }
670 732
671 double 733 double
672 Colour3DPlotLayer::getYForBin(LayerGeometryProvider *v, double bin) const 734 Colour3DPlotLayer::getYForBin(const LayerGeometryProvider *v, double bin) const
673 { 735 {
674 double y = bin; 736 double y = bin;
675 if (!m_model) return y; 737 if (!m_model) return y;
676 double mn = 0, mx = m_model->getHeight(); 738 double mn = 0, mx = m_model->getHeight();
677 getDisplayExtents(mn, mx); 739 getDisplayExtents(mn, mx);
678 double h = v->getPaintHeight(); 740 double h = v->getPaintHeight();
679 if (m_binScale == LinearBinScale) { 741 if (m_binScale == BinScale::Linear) {
680 y = h - (((bin - mn) * h) / (mx - mn)); 742 y = h - (((bin - mn) * h) / (mx - mn));
681 } else { 743 } else {
682 double logmin = mn + 1, logmax = mx + 1; 744 double logmin = mn + 1, logmax = mx + 1;
683 LogRange::mapRange(logmin, logmax); 745 LogRange::mapRange(logmin, logmax);
684 y = h - (((LogRange::map(bin + 1) - logmin) * h) / (logmax - logmin)); 746 y = h - (((LogRange::map(bin + 1) - logmin) * h) / (logmax - logmin));
685 } 747 }
686 return y; 748 return y;
687 } 749 }
688 750
689 int
690 Colour3DPlotLayer::getIYForBin(LayerGeometryProvider *v, int bin) const
691 {
692 return int(round(getYForBin(v, bin)));
693 }
694
695 double 751 double
696 Colour3DPlotLayer::getBinForY(LayerGeometryProvider *v, double y) const 752 Colour3DPlotLayer::getBinForY(const LayerGeometryProvider *v, double y) const
697 { 753 {
698 double bin = y; 754 double bin = y;
699 if (!m_model) return bin; 755 if (!m_model) return bin;
700 double mn = 0, mx = m_model->getHeight(); 756 double mn = 0, mx = m_model->getHeight();
701 getDisplayExtents(mn, mx); 757 getDisplayExtents(mn, mx);
702 double h = v->getPaintHeight(); 758 double h = v->getPaintHeight();
703 if (m_binScale == LinearBinScale) { 759 if (m_binScale == BinScale::Linear) {
704 bin = mn + ((h - y) * (mx - mn)) / h; 760 bin = mn + ((h - y) * (mx - mn)) / h;
705 } else { 761 } else {
706 double logmin = mn + 1, logmax = mx + 1; 762 double logmin = mn + 1, logmax = mx + 1;
707 LogRange::mapRange(logmin, logmax); 763 LogRange::mapRange(logmin, logmax);
708 bin = LogRange::unmap(logmin + ((h - y) * (logmax - logmin)) / h) - 1; 764 bin = LogRange::unmap(logmin + ((h - y) * (logmax - logmin)) / h) - 1;
709 } 765 }
710 return bin; 766 return bin;
711 }
712
713 int
714 Colour3DPlotLayer::getIBinForY(LayerGeometryProvider *v, int y) const
715 {
716 return int(floor(getBinForY(v, y)));
717 } 767 }
718 768
719 QString 769 QString
720 Colour3DPlotLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const 770 Colour3DPlotLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const
721 { 771 {
816 int h = rect.height(), w = rect.width(); 866 int h = rect.height(), w = rect.width();
817 867
818 int cw = getColourScaleWidth(paint); 868 int cw = getColourScaleWidth(paint);
819 869
820 int ch = h - 20; 870 int ch = h - 20;
821 if (ch > 20 && m_cache) { 871 if (ch > 20) {
822 872
823 double min = m_model->getMinimumLevel(); 873 double min = m_viewMags[v->getId()].getMin();
824 double max = m_model->getMaximumLevel(); 874 double max = m_viewMags[v->getId()].getMax();
825 875
826 double mmin = min; 876 if (max <= min) max = min + 0.1;
827 double mmax = max; 877
828
829 if (m_colourScale == LogScale) {
830 LogRange::mapRange(mmin, mmax);
831 } else if (m_colourScale == PlusMinusOneScale) {
832 mmin = -1.f;
833 mmax = 1.f;
834 } else if (m_colourScale == AbsoluteScale) {
835 if (mmin < 0) {
836 if (fabs(mmin) > fabs(mmax)) mmax = fabs(mmin);
837 else mmax = fabs(mmax);
838 mmin = 0;
839 } else {
840 mmin = fabs(mmin);
841 mmax = fabs(mmax);
842 }
843 }
844
845 if (max == min) max = min + 1.f;
846 if (mmax == mmin) mmax = mmin + 1.f;
847
848 paint.setPen(v->getForeground()); 878 paint.setPen(v->getForeground());
849 paint.drawRect(4, 10, cw - 8, ch+1); 879 paint.drawRect(4, 10, cw - 8, ch+1);
850 880
851 for (int y = 0; y < ch; ++y) { 881 for (int y = 0; y < ch; ++y) {
852 double value = ((max - min) * (double(ch-y) - 1.0)) / double(ch) + min; 882 double value = ((max - min) * (double(ch-y) - 1.0)) / double(ch) + min;
853 if (m_colourScale == LogScale) { 883 paint.setPen(getRenderer(v)->getColour(value));
854 value = LogRange::map(value); 884 paint.drawLine(5, 11 + y, cw - 5, 11 + y);
855 }
856 int pixel = int(((value - mmin) * 256) / (mmax - mmin));
857 if (pixel >= 0 && pixel < 256) {
858 QRgb c = m_cache->color(pixel);
859 paint.setPen(QColor(qRed(c), qGreen(c), qBlue(c)));
860 paint.drawLine(5, 11 + y, cw - 5, 11 + y);
861 } else {
862 cerr << "WARNING: Colour3DPlotLayer::paintVerticalScale: value " << value << ", mmin " << mmin << ", mmax " << mmax << " leads to invalid pixel " << pixel << endl;
863 }
864 } 885 }
865 886
866 QString minstr = QString("%1").arg(min); 887 QString minstr = QString("%1").arg(min);
867 QString maxstr = QString("%1").arg(max); 888 QString maxstr = QString("%1").arg(max);
868 889
869 paint.save(); 890 paint.save();
870 891
871 QFont font = paint.font(); 892 QFont font = paint.font();
872 font.setPixelSize(int(font.pixelSize() * 0.65)); 893 if (font.pixelSize() > 0) {
873 paint.setFont(font); 894 int newSize = int(font.pixelSize() * 0.65);
895 if (newSize < 6) newSize = 6;
896 font.setPixelSize(newSize);
897 paint.setFont(font);
898 }
874 899
875 int msw = paint.fontMetrics().width(maxstr); 900 int msw = paint.fontMetrics().width(maxstr);
876 901
877 QMatrix m; 902 QMatrix m;
878 m.translate(cw - 6, ch + 10); 903 m.translate(cw - 6, ch + 10);
879 m.rotate(-90); 904 m.rotate(-90);
880 905
881 paint.setWorldMatrix(m); 906 paint.setWorldMatrix(m);
882 907
883 v->drawVisibleText(paint, 2, 0, minstr, View::OutlinedText); 908 PaintAssistant::drawVisibleText(v, paint, 2, 0, minstr, PaintAssistant::OutlinedText);
884 909
885 m.translate(ch - msw - 2, 0); 910 m.translate(ch - msw - 2, 0);
886 paint.setWorldMatrix(m); 911 paint.setWorldMatrix(m);
887 912
888 v->drawVisibleText(paint, 0, 0, maxstr, View::OutlinedText); 913 PaintAssistant::drawVisibleText(v, paint, 0, 0, maxstr, PaintAssistant::OutlinedText);
889 914
890 paint.restore(); 915 paint.restore();
891 } 916 }
892 917
893 paint.setPen(v->getForeground()); 918 paint.setPen(v->getForeground());
955 DenseThreeDimensionalModel::Column 980 DenseThreeDimensionalModel::Column
956 Colour3DPlotLayer::getColumn(int col) const 981 Colour3DPlotLayer::getColumn(int col) const
957 { 982 {
958 Profiler profiler("Colour3DPlotLayer::getColumn"); 983 Profiler profiler("Colour3DPlotLayer::getColumn");
959 984
960 DenseThreeDimensionalModel::Column prev;
961 if (m_rectified && (col > m_model->getStartFrame())) {
962 prev = m_model->getColumn(col - 1);
963 }
964
965 DenseThreeDimensionalModel::Column values = m_model->getColumn(col); 985 DenseThreeDimensionalModel::Column values = m_model->getColumn(col);
966 986 values.resize(m_model->getHeight(), 0.f);
967 if (m_rectified && !prev.empty()) { 987 if (m_normalization != ColumnNormalization::Max1 &&
968 for (int y = 0; y < values.size(); ++y) { 988 m_normalization != ColumnNormalization::Hybrid) {
969 if (values[y] < prev[y]) values[y] = 0; 989 return values;
970 else values[y] -= prev[y]; 990 }
971 }
972 }
973
974 while (values.size() < m_model->getHeight()) values.push_back(0.f);
975 if (!m_normalizeColumns && !m_normalizeHybrid) return values;
976 991
977 double colMax = 0.f, colMin = 0.f; 992 double colMax = 0.f, colMin = 0.f;
978 double min = 0.f, max = 0.f; 993 double min = 0.f, max = 0.f;
979 994
995 int nv = int(values.size());
996
980 min = m_model->getMinimumLevel(); 997 min = m_model->getMinimumLevel();
981 max = m_model->getMaximumLevel(); 998 max = m_model->getMaximumLevel();
982 999
983 for (int y = 0; y < values.size(); ++y) { 1000 for (int y = 0; y < nv; ++y) {
984 if (y == 0 || values.at(y) > colMax) colMax = values.at(y); 1001 if (y == 0 || values.at(y) > colMax) colMax = values.at(y);
985 if (y == 0 || values.at(y) < colMin) colMin = values.at(y); 1002 if (y == 0 || values.at(y) < colMin) colMin = values.at(y);
986 } 1003 }
987 if (colMin == colMax) colMax = colMin + 1; 1004 if (colMin == colMax) colMax = colMin + 1;
988 1005
989 for (int y = 0; y < values.size(); ++y) { 1006 for (int y = 0; y < nv; ++y) {
990 1007
991 double value = values.at(y); 1008 double value = values.at(y);
992 double norm = (value - colMin) / (colMax - colMin); 1009 double norm = (value - colMin) / (colMax - colMin);
993 double newvalue = min + (max - min) * norm; 1010 double newvalue = min + (max - min) * norm;
994 1011
995 if (value != newvalue) values[y] = float(newvalue); 1012 if (value != newvalue) values[y] = float(newvalue);
996 } 1013 }
997 1014
998 if (m_normalizeHybrid && (colMax > 0.0)) { 1015 if (m_normalization == ColumnNormalization::Hybrid
1016 && (colMax > 0.0)) {
999 double logmax = log10(colMax); 1017 double logmax = log10(colMax);
1000 for (int y = 0; y < values.size(); ++y) { 1018 for (int y = 0; y < nv; ++y) {
1001 values[y] = float(values[y] * logmax); 1019 values[y] = float(values[y] * logmax);
1002 } 1020 }
1003 } 1021 }
1004 1022
1005 return values; 1023 return values;
1006 } 1024 }
1007 1025
1008 void 1026 Colour3DPlotRenderer *
1009 Colour3DPlotLayer::fillCache(int firstBin, int lastBin) const 1027 Colour3DPlotLayer::getRenderer(const LayerGeometryProvider *v) const
1010 { 1028 {
1011 Profiler profiler("Colour3DPlotLayer::fillCache", true); 1029 if (m_renderers.find(v->getId()) == m_renderers.end()) {
1012 1030
1013 sv_frame_t modelStart = m_model->getStartFrame(); 1031 Colour3DPlotRenderer::Sources sources;
1014 sv_frame_t modelEnd = m_model->getEndFrame(); 1032 sources.verticalBinLayer = this;
1015 int modelResolution = m_model->getResolution(); 1033 sources.fft = 0;
1016 1034 sources.source = m_model;
1017 int modelStartBin = int(modelStart / modelResolution); 1035 sources.peaks = getPeakCache();
1018 int modelEndBin = int(modelEnd / modelResolution); 1036
1019 1037 ColourScale::Parameters cparams;
1020 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1038 cparams.colourMap = m_colourMap;
1021 cerr << "Colour3DPlotLayer::fillCache: range " << firstBin << " -> " << lastBin << " of model range " << modelStartBin << " -> " << modelEndBin << " (model resolution " << modelResolution << ")" << endl; 1039 cparams.scaleType = m_colourScale;
1022 #endif 1040 cparams.gain = m_gain;
1023 1041
1024 int cacheWidth = modelEndBin - modelStartBin + 1; 1042 if (m_normalization == ColumnNormalization::None) {
1025 if (lastBin > modelEndBin) cacheWidth = lastBin - modelStartBin + 1; 1043 cparams.minValue = m_model->getMinimumLevel();
1026 int cacheHeight = m_model->getHeight(); 1044 cparams.maxValue = m_model->getMaximumLevel();
1027 1045 } else if (m_normalization == ColumnNormalization::Hybrid) {
1028 if (m_cache && m_cache->height() != cacheHeight) { 1046 cparams.minValue = 0;
1029 // height has changed: delete everything rather than resizing 1047 cparams.maxValue = log10(m_model->getMaximumLevel() + 1.0);
1030 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1048 }
1031 cerr << "Colour3DPlotLayer::fillCache: Cache height has changed, recreating" << endl; 1049
1032 #endif 1050 if (cparams.maxValue <= cparams.minValue) {
1033 delete m_cache; 1051 cparams.maxValue = cparams.minValue + 0.1;
1034 delete m_peaksCache; 1052 }
1035 m_cache = 0;
1036 m_peaksCache = 0;
1037 }
1038
1039 if (m_cache && m_cache->width() != cacheWidth) {
1040 // width has changed and we have an existing cache: resize it
1041 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
1042 cerr << "Colour3DPlotLayer::fillCache: Cache width has changed, resizing existing cache" << endl;
1043 #endif
1044 QImage *newCache =
1045 new QImage(m_cache->copy(0, 0, cacheWidth, cacheHeight));
1046 delete m_cache;
1047 m_cache = newCache;
1048 if (m_peaksCache) {
1049 QImage *newPeaksCache =
1050 new QImage(m_peaksCache->copy
1051 (0, 0, cacheWidth / m_peakResolution + 1, cacheHeight));
1052 delete m_peaksCache;
1053 m_peaksCache = newPeaksCache;
1054 }
1055 }
1056
1057 if (!m_cache) {
1058 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
1059 cerr << "Colour3DPlotLayer::fillCache: Have no cache, making one" << endl;
1060 #endif
1061 m_cache = new QImage
1062 (cacheWidth, cacheHeight, QImage::Format_Indexed8);
1063 m_cache->setColorCount(256);
1064 m_cache->fill(0);
1065 if (!m_normalizeVisibleArea) {
1066 m_peaksCache = new QImage
1067 (cacheWidth / m_peakResolution + 1, cacheHeight,
1068 QImage::Format_Indexed8);
1069 m_peaksCache->setColorCount(256);
1070 m_peaksCache->fill(0);
1071 } else if (m_peaksCache) {
1072 delete m_peaksCache;
1073 m_peaksCache = 0;
1074 }
1075 m_cacheValidStart = 0;
1076 m_cacheValidEnd = 0;
1077 }
1078
1079 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
1080 cerr << "cache size = " << m_cache->width() << "x" << m_cache->height()
1081 << " peaks cache size = " << m_peaksCache->width() << "x" << m_peaksCache->height() << endl;
1082 #endif
1083
1084 if (m_cacheValidStart <= firstBin && m_cacheValidEnd >= lastBin) {
1085 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
1086 cerr << "Cache is valid in this region already" << endl;
1087 #endif
1088 return;
1089 }
1090
1091 int fillStart = firstBin;
1092 int fillEnd = lastBin;
1093
1094 if (fillStart < modelStartBin) fillStart = modelStartBin;
1095 if (fillStart > modelEndBin) fillStart = modelEndBin;
1096 if (fillEnd < modelStartBin) fillEnd = modelStartBin;
1097 if (fillEnd > modelEndBin) fillEnd = modelEndBin;
1098
1099 bool normalizeVisible = (m_normalizeVisibleArea && !m_normalizeColumns);
1100
1101 if (!normalizeVisible && (m_cacheValidStart < m_cacheValidEnd)) {
1102 1053
1103 if (m_cacheValidEnd < fillStart) { 1054 Colour3DPlotRenderer::Parameters params;
1104 fillStart = m_cacheValidEnd + 1; 1055 params.colourScale = ColourScale(cparams);
1105 } 1056 params.normalization = m_normalization;
1106 if (m_cacheValidStart > fillEnd) { 1057 params.binScale = m_binScale;
1107 fillEnd = m_cacheValidStart - 1; 1058 params.alwaysOpaque = m_opaque;
1108 } 1059 params.invertVertical = m_invertVertical;
1060 params.interpolate = m_smooth;
1061
1062 m_renderers[v->getId()] = new Colour3DPlotRenderer(sources, params);
1063 }
1064
1065 return m_renderers[v->getId()];
1066 }
1067
1068 void
1069 Colour3DPlotLayer::paintWithRenderer(LayerGeometryProvider *v,
1070 QPainter &paint, QRect rect) const
1071 {
1072 Colour3DPlotRenderer *renderer = getRenderer(v);
1073
1074 Colour3DPlotRenderer::RenderResult result;
1075 MagnitudeRange magRange;
1076 int viewId = v->getId();
1077
1078 if (!renderer->geometryChanged(v)) {
1079 magRange = m_viewMags[viewId];
1080 }
1081
1082 if (m_synchronous) {
1083
1084 result = renderer->render(v, paint, rect);
1085
1086 } else {
1087
1088 result = renderer->renderTimeConstrained(v, paint, rect);
1089
1090 QRect uncached = renderer->getLargestUncachedRect(v);
1091 if (uncached.width() > 0) {
1092 v->updatePaintRect(uncached);
1093 }
1094 }
1095
1096 magRange.sample(result.range);
1097
1098 if (magRange.isSet()) {
1099 if (!(m_viewMags[viewId] == magRange)) {
1100 m_viewMags[viewId] = magRange;
1101 //!!! now need to do the normalise-visible thing
1102 }
1103 }
1104
1105 cerr << "mag range in this view: "
1106 << m_viewMags[v->getId()].getMin()
1107 << " -> "
1108 << m_viewMags[v->getId()].getMax()
1109 << endl;
1109 1110
1110 m_cacheValidStart = std::min(fillStart, m_cacheValidStart);
1111 m_cacheValidEnd = std::max(fillEnd, m_cacheValidEnd);
1112
1113 } else {
1114
1115 // when normalising the visible area, the only valid area,
1116 // ever, is the currently visible one
1117
1118 m_cacheValidStart = fillStart;
1119 m_cacheValidEnd = fillEnd;
1120 }
1121
1122 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
1123 cerr << "Cache size " << cacheWidth << "x" << cacheHeight << " will be valid from " << m_cacheValidStart << " to " << m_cacheValidEnd << " (fillStart = " << fillStart << ", fillEnd = " << fillEnd << ")" << endl;
1124 #endif
1125
1126 DenseThreeDimensionalModel::Column values;
1127
1128 double min = m_model->getMinimumLevel();
1129 double max = m_model->getMaximumLevel();
1130
1131 if (m_colourScale == LogScale) {
1132 LogRange::mapRange(min, max);
1133 } else if (m_colourScale == PlusMinusOneScale) {
1134 min = -1.f;
1135 max = 1.f;
1136 } else if (m_colourScale == AbsoluteScale) {
1137 if (min < 0) {
1138 if (fabs(min) > fabs(max)) max = fabs(min);
1139 else max = fabs(max);
1140 min = 0;
1141 } else {
1142 min = fabs(min);
1143 max = fabs(max);
1144 }
1145 }
1146
1147 if (max == min) max = min + 1.f;
1148
1149 ColourMapper mapper(m_colourMap, 0.f, 255.f);
1150
1151 for (int index = 0; index < 256; ++index) {
1152 QColor colour = mapper.map(index);
1153 m_cache->setColor
1154 (index, qRgb(colour.red(), colour.green(), colour.blue()));
1155 if (m_peaksCache) {
1156 m_peaksCache->setColor
1157 (index, qRgb(colour.red(), colour.green(), colour.blue()));
1158 }
1159 }
1160
1161 double visibleMax = 0.f, visibleMin = 0.f;
1162
1163 if (normalizeVisible) {
1164
1165 for (int c = fillStart; c <= fillEnd; ++c) {
1166
1167 values = getColumn(c);
1168
1169 double colMax = 0.f, colMin = 0.f;
1170
1171 for (int y = 0; y < cacheHeight; ++y) {
1172 if (y >= values.size()) break;
1173 if (y == 0 || values[y] > colMax) colMax = values[y];
1174 if (y == 0 || values[y] < colMin) colMin = values[y];
1175 }
1176
1177 if (c == fillStart || colMax > visibleMax) visibleMax = colMax;
1178 if (c == fillStart || colMin < visibleMin) visibleMin = colMin;
1179 }
1180
1181 if (m_colourScale == LogScale) {
1182 visibleMin = LogRange::map(visibleMin);
1183 visibleMax = LogRange::map(visibleMax);
1184 if (visibleMin > visibleMax) std::swap(visibleMin, visibleMax);
1185 } else if (m_colourScale == AbsoluteScale) {
1186 if (visibleMin < 0) {
1187 if (fabs(visibleMin) > fabs(visibleMax)) visibleMax = fabs(visibleMin);
1188 else visibleMax = fabs(visibleMax);
1189 visibleMin = 0;
1190 } else {
1191 visibleMin = fabs(visibleMin);
1192 visibleMax = fabs(visibleMax);
1193 }
1194 }
1195 }
1196
1197 if (visibleMin == visibleMax) visibleMax = visibleMin + 1;
1198
1199 int *peaks = 0;
1200 if (m_peaksCache) {
1201 peaks = new int[cacheHeight];
1202 for (int y = 0; y < cacheHeight; ++y) {
1203 peaks[y] = 0;
1204 }
1205 }
1206
1207 Profiler profiler2("Colour3DPlotLayer::fillCache: filling", true);
1208
1209 for (int c = fillStart; c <= fillEnd; ++c) {
1210
1211 values = getColumn(c);
1212
1213 if (c >= m_cache->width()) {
1214 cerr << "ERROR: column " << c << " >= cache width "
1215 << m_cache->width() << endl;
1216 continue;
1217 }
1218
1219 for (int y = 0; y < cacheHeight; ++y) {
1220
1221 double value = min;
1222 if (y < values.size()) {
1223 value = values.at(y);
1224 }
1225
1226 value = value * m_gain;
1227
1228 if (m_colourScale == LogScale) {
1229 value = LogRange::map(value);
1230 } else if (m_colourScale == AbsoluteScale) {
1231 value = fabs(value);
1232 }
1233
1234 if (normalizeVisible) {
1235 double norm = (value - visibleMin) / (visibleMax - visibleMin);
1236 value = min + (max - min) * norm;
1237 }
1238
1239 int pixel = int(((value - min) * 256) / (max - min));
1240 if (pixel < 0) pixel = 0;
1241 if (pixel > 255) pixel = 255;
1242 if (peaks && (pixel > peaks[y])) peaks[y] = pixel;
1243
1244 if (m_invertVertical) {
1245 m_cache->setPixel(c, cacheHeight - y - 1, pixel);
1246 } else {
1247 if (y >= m_cache->height()) {
1248 cerr << "ERROR: row " << y << " >= cache height " << m_cache->height() << endl;
1249 } else {
1250 m_cache->setPixel(c, y, pixel);
1251 }
1252 }
1253 }
1254
1255 if (peaks) {
1256 int notch = (c % m_peakResolution);
1257 if (notch == m_peakResolution-1 || c == fillEnd) {
1258 int pc = c / m_peakResolution;
1259 if (pc >= m_peaksCache->width()) {
1260 cerr << "ERROR: peak column " << pc
1261 << " (from col " << c << ") >= peaks cache width "
1262 << m_peaksCache->width() << endl;
1263 continue;
1264 }
1265 for (int y = 0; y < cacheHeight; ++y) {
1266 if (m_invertVertical) {
1267 m_peaksCache->setPixel(pc, cacheHeight - y - 1, peaks[y]);
1268 } else {
1269 if (y >= m_peaksCache->height()) {
1270 cerr << "ERROR: row " << y
1271 << " >= peaks cache height "
1272 << m_peaksCache->height() << endl;
1273 } else {
1274 m_peaksCache->setPixel(pc, y, peaks[y]);
1275 }
1276 }
1277 }
1278 for (int y = 0; y < cacheHeight; ++y) {
1279 peaks[y] = 0;
1280 }
1281 }
1282 }
1283 }
1284
1285 delete[] peaks;
1286 }
1287
1288 bool
1289 Colour3DPlotLayer::shouldPaintDenseIn(const LayerGeometryProvider *v) const
1290 {
1291 if (!m_model || !v || !(v->getViewManager())) {
1292 return false;
1293 }
1294 double srRatio =
1295 v->getViewManager()->getMainModelSampleRate() / m_model->getSampleRate();
1296 if (m_opaque ||
1297 m_smooth ||
1298 m_model->getHeight() >= v->getPaintHeight() ||
1299 ((m_model->getResolution() * srRatio) / v->getZoomLevel()) < 2) {
1300 return true;
1301 }
1302 return false;
1303 } 1111 }
1304 1112
1305 void 1113 void
1306 Colour3DPlotLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const 1114 Colour3DPlotLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const
1307 { 1115 {
1322 10, QColor(120, 120, 120)); 1130 10, QColor(120, 120, 120));
1323 } 1131 }
1324 return; 1132 return;
1325 } 1133 }
1326 1134
1327 if (m_normalizeVisibleArea && !m_normalizeColumns) rect = v->getPaintRect(); 1135 if (m_model->getWidth() == 0) {
1328
1329 sv_frame_t modelStart = m_model->getStartFrame();
1330 sv_frame_t modelEnd = m_model->getEndFrame();
1331 int modelResolution = m_model->getResolution();
1332
1333 // The cache is from the model's start frame to the model's end
1334 // frame at the model's window increment frames per pixel. We
1335 // want to draw from our start frame + x0 * zoomLevel to our start
1336 // frame + x1 * zoomLevel at zoomLevel frames per pixel.
1337
1338 // We have quite different paint mechanisms for rendering "large"
1339 // bins (more than one bin per pixel in both directions) and
1340 // "small". This is "large"; see paintDense below for "small".
1341
1342 int x0 = rect.left();
1343 int x1 = rect.right() + 1;
1344
1345 int h = v->getPaintHeight();
1346
1347 double srRatio =
1348 v->getViewManager()->getMainModelSampleRate() / m_model->getSampleRate();
1349
1350 int sx0 = int((double(v->getFrameForX(x0)) / srRatio - double(modelStart))
1351 / modelResolution);
1352 int sx1 = int((double(v->getFrameForX(x1)) / srRatio - double(modelStart))
1353 / modelResolution);
1354 int sh = m_model->getHeight();
1355
1356 int symin = m_miny;
1357 int symax = m_maxy;
1358 if (symax <= symin) {
1359 symin = 0;
1360 symax = sh;
1361 }
1362 if (symin < 0) symin = 0;
1363 if (symax > sh) symax = sh;
1364
1365 if (sx0 > 0) --sx0;
1366 fillCache(sx0 < 0 ? 0 : sx0,
1367 sx1 < 0 ? 0 : sx1);
1368
1369 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1136 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
1370 cerr << "Colour3DPlotLayer::paint: height = "<< m_model->getHeight() << ", modelStart = " << modelStart << ", resolution = " << modelResolution << ", model rate = " << m_model->getSampleRate() << " (zoom level = " << v->getZoomLevel() << ", srRatio = " << srRatio << ")" << endl; 1137 cerr << "Colour3DPlotLayer::paint(): model width == 0, "
1138 << "nothing to paint (yet)" << endl;
1371 #endif 1139 #endif
1372
1373 if (shouldPaintDenseIn(v)) {
1374 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
1375 cerr << "calling paintDense" << endl;
1376 #endif
1377 paintDense(v, paint, rect);
1378 return; 1140 return;
1379 } 1141 }
1380 1142
1381 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1143 //!!!???
1382 cerr << "Colour3DPlotLayer::paint: w " << x1-x0 << ", h " << h << ", sx0 " << sx0 << ", sx1 " << sx1 << ", sw " << sx1-sx0 << ", sh " << sh << endl; 1144
1383 cerr << "Colour3DPlotLayer: sample rate is " << m_model->getSampleRate() << ", resolution " << m_model->getResolution() << endl; 1145 if (m_normalizeVisibleArea) {
1384 #endif 1146 rect = v->getPaintRect();
1385 1147 }
1386 QPoint illuminatePos; 1148
1387 bool illuminate = v->shouldIlluminateLocalFeatures(this, illuminatePos); 1149 //!!! why is the setLayerDormant(false) found here in
1388 1150 //!!! SpectrogramLayer not present in Colour3DPlotLayer?
1389 const int buflen = 40; 1151 //!!! unnecessary? vestigial? forgotten?
1390 char labelbuf[buflen]; 1152
1391 1153 paintWithRenderer(v, paint, rect);
1392 for (int sx = sx0; sx <= sx1; ++sx) {
1393
1394 sv_frame_t fx = sx * modelResolution;
1395
1396 if (fx + modelResolution <= modelStart || fx > modelEnd) continue;
1397
1398 int rx0 = v->getXForFrame(int(double(fx + modelStart) * srRatio));
1399 int rx1 = v->getXForFrame(int(double(fx + modelStart + modelResolution + 1) * srRatio));
1400
1401 int rw = rx1 - rx0;
1402 if (rw < 1) rw = 1;
1403
1404 bool showLabel = (rw > 10 &&
1405 paint.fontMetrics().width("0.000000") < rw - 3 &&
1406 paint.fontMetrics().height() < (h / sh));
1407
1408 for (int sy = symin; sy < symax; ++sy) {
1409
1410 int ry0 = getIYForBin(v, sy);
1411 int ry1 = getIYForBin(v, sy + 1);
1412 QRect r(rx0, ry1, rw, ry0 - ry1);
1413
1414 QRgb pixel = qRgb(255, 255, 255);
1415 if (sx >= 0 && sx < m_cache->width() &&
1416 sy >= 0 && sy < m_cache->height()) {
1417 pixel = m_cache->pixel(sx, sy);
1418 }
1419
1420 if (rw == 1) {
1421 paint.setPen(pixel);
1422 paint.setBrush(Qt::NoBrush);
1423 paint.drawLine(r.x(), r.y(), r.x(), r.y() + r.height() - 1);
1424 continue;
1425 }
1426
1427 QColor pen(255, 255, 255, 80);
1428 QColor brush(pixel);
1429
1430 if (rw > 3 && r.height() > 3) {
1431 brush.setAlpha(160);
1432 }
1433
1434 paint.setPen(Qt::NoPen);
1435 paint.setBrush(brush);
1436
1437 if (illuminate) {
1438 if (r.contains(illuminatePos)) {
1439 paint.setPen(v->getForeground());
1440 }
1441 }
1442
1443 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
1444 // cerr << "rect " << r.x() << "," << r.y() << " "
1445 // << r.width() << "x" << r.height() << endl;
1446 #endif
1447
1448 paint.drawRect(r);
1449
1450 if (showLabel) {
1451 if (sx >= 0 && sx < m_cache->width() &&
1452 sy >= 0 && sy < m_cache->height()) {
1453 double value = m_model->getValueAt(sx, sy);
1454 snprintf(labelbuf, buflen, "%06f", value);
1455 QString text(labelbuf);
1456 paint.setPen(v->getBackground());
1457 paint.drawText(rx0 + 2,
1458 ry0 - h / sh - 1 + 2 + paint.fontMetrics().ascent(),
1459 text);
1460 }
1461 }
1462 }
1463 }
1464 }
1465
1466 void
1467 Colour3DPlotLayer::paintDense(LayerGeometryProvider *v, QPainter &paint, QRect rect) const
1468 {
1469 Profiler profiler("Colour3DPlotLayer::paintDense", true);
1470 if (!m_cache) return;
1471
1472 double modelStart = double(m_model->getStartFrame());
1473 double modelResolution = double(m_model->getResolution());
1474
1475 sv_samplerate_t mmsr = v->getViewManager()->getMainModelSampleRate();
1476 sv_samplerate_t msr = m_model->getSampleRate();
1477 double srRatio = mmsr / msr;
1478
1479 int x0 = rect.left();
1480 int x1 = rect.right() + 1;
1481
1482 const int w = x1 - x0; // const so it can be used as array size below
1483 int h = v->getPaintHeight(); // we always paint full height
1484 int sh = m_model->getHeight();
1485
1486 int symin = m_miny;
1487 int symax = m_maxy;
1488 if (symax <= symin) {
1489 symin = 0;
1490 symax = sh;
1491 }
1492 if (symin < 0) symin = 0;
1493 if (symax > sh) symax = sh;
1494
1495 QImage img(w, h, QImage::Format_Indexed8);
1496 img.setColorTable(m_cache->colorTable());
1497
1498 uchar *peaks = new uchar[w];
1499 memset(peaks, 0, w);
1500
1501 int zoomLevel = v->getZoomLevel();
1502
1503 QImage *source = m_cache;
1504
1505 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
1506 cerr << "modelResolution " << modelResolution << ", srRatio "
1507 << srRatio << ", m_peakResolution " << m_peakResolution
1508 << ", zoomLevel " << zoomLevel << ", result "
1509 << ((modelResolution * srRatio * m_peakResolution) / zoomLevel)
1510 << endl;
1511 #endif
1512
1513 if (m_peaksCache) {
1514 if (((modelResolution * srRatio * m_peakResolution) / zoomLevel) < 1) {
1515 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
1516 cerr << "using peaks cache" << endl;
1517 #endif
1518 source = m_peaksCache;
1519 modelResolution *= m_peakResolution;
1520 } else {
1521 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
1522 cerr << "not using peaks cache" << endl;
1523 #endif
1524 }
1525 } else {
1526 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
1527 cerr << "have no peaks cache" << endl;
1528 #endif
1529 }
1530
1531 int sw = source->width();
1532
1533 sv_frame_t xf = -1;
1534 sv_frame_t nxf = v->getFrameForX(x0);
1535
1536 double epsilon = 0.000001;
1537
1538 vector<double> sxa(w*2);
1539
1540 for (int x = 0; x < w; ++x) {
1541
1542 xf = nxf;
1543 nxf = xf + zoomLevel;
1544
1545 double sx0 = (double(xf) / srRatio - modelStart) / modelResolution;
1546 double sx1 = (double(nxf) / srRatio - modelStart) / modelResolution;
1547
1548 sxa[x*2] = sx0;
1549 sxa[x*2 + 1] = sx1;
1550 }
1551
1552 double logmin = symin+1, logmax = symax+1;
1553 LogRange::mapRange(logmin, logmax);
1554
1555 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
1556 cerr << "m_smooth = " << m_smooth << ", w = " << w << ", h = " << h << endl;
1557 #endif
1558
1559 if (m_smooth) {
1560
1561 for (int y = 0; y < h; ++y) {
1562
1563 double sy = getBinForY(v, y) - 0.5;
1564 int syi = int(sy + epsilon);
1565 if (syi < 0 || syi >= source->height()) continue;
1566
1567 uchar *targetLine = img.scanLine(y);
1568 uchar *sourceLine = source->scanLine(syi);
1569 uchar *nextSource;
1570 if (syi + 1 < source->height()) {
1571 nextSource = source->scanLine(syi + 1);
1572 } else {
1573 nextSource = sourceLine;
1574 }
1575
1576 for (int x = 0; x < w; ++x) {
1577
1578 targetLine[x] = 0;
1579
1580 double sx0 = sxa[x*2];
1581 if (sx0 < 0) continue;
1582 int sx0i = int(sx0 + epsilon);
1583 if (sx0i >= sw) break;
1584
1585 double a = sourceLine[sx0i];
1586 double b = a;
1587 double value;
1588
1589 double sx1 = sxa[x*2+1];
1590 if (sx1 > sx0 + 1.f) {
1591 int sx1i = int(sx1);
1592 bool have = false;
1593 for (int sx = sx0i; sx <= sx1i; ++sx) {
1594 if (sx < 0 || sx >= sw) continue;
1595 if (!have) {
1596 a = sourceLine[sx];
1597 b = nextSource[sx];
1598 have = true;
1599 } else {
1600 a = std::max(a, double(sourceLine[sx]));
1601 b = std::max(b, double(nextSource[sx]));
1602 }
1603 }
1604 double yprop = sy - syi;
1605 value = (a * (1.f - yprop) + b * yprop);
1606 } else {
1607 a = sourceLine[sx0i];
1608 b = nextSource[sx0i];
1609 double yprop = sy - syi;
1610 value = (a * (1.f - yprop) + b * yprop);
1611 int oi = sx0i + 1;
1612 double xprop = sx0 - sx0i;
1613 xprop -= 0.5;
1614 if (xprop < 0) {
1615 oi = sx0i - 1;
1616 xprop = -xprop;
1617 }
1618 if (oi < 0 || oi >= sw) oi = sx0i;
1619 a = sourceLine[oi];
1620 b = nextSource[oi];
1621 value = (value * (1.f - xprop) +
1622 (a * (1.f - yprop) + b * yprop) * xprop);
1623 }
1624
1625 int vi = int(lrint(value));
1626 if (vi > 255) vi = 255;
1627 if (vi < 0) vi = 0;
1628 targetLine[x] = uchar(vi);
1629 }
1630 }
1631 } else {
1632
1633 double sy0 = getBinForY(v, 0);
1634
1635 int psy0i = -1, psy1i = -1;
1636
1637 for (int y = 0; y < h; ++y) {
1638
1639 double sy1 = sy0;
1640 sy0 = getBinForY(v, double(y + 1));
1641
1642 int sy0i = int(sy0 + epsilon);
1643 int sy1i = int(sy1);
1644
1645 uchar *targetLine = img.scanLine(y);
1646
1647 if (sy0i == psy0i && sy1i == psy1i) {
1648 // same source scan line as just computed
1649 goto copy;
1650 }
1651
1652 psy0i = sy0i;
1653 psy1i = sy1i;
1654
1655 for (int x = 0; x < w; ++x) {
1656 peaks[x] = 0;
1657 }
1658
1659 for (int sy = sy0i; sy <= sy1i; ++sy) {
1660
1661 if (sy < 0 || sy >= source->height()) continue;
1662
1663 uchar *sourceLine = source->scanLine(sy);
1664
1665 for (int x = 0; x < w; ++x) {
1666
1667 double sx1 = sxa[x*2 + 1];
1668 if (sx1 < 0) continue;
1669 int sx1i = int(sx1);
1670
1671 double sx0 = sxa[x*2];
1672 if (sx0 < 0) continue;
1673 int sx0i = int(sx0 + epsilon);
1674 if (sx0i >= sw) break;
1675
1676 uchar peak = 0;
1677 for (int sx = sx0i; sx <= sx1i; ++sx) {
1678 if (sx < 0 || sx >= sw) continue;
1679 if (sourceLine[sx] > peak) peak = sourceLine[sx];
1680 }
1681 peaks[x] = peak;
1682 }
1683 }
1684
1685 copy:
1686 for (int x = 0; x < w; ++x) {
1687 targetLine[x] = peaks[x];
1688 }
1689 }
1690 }
1691
1692 delete[] peaks;
1693
1694 paint.drawImage(x0, 0, img);
1695 } 1154 }
1696 1155
1697 bool 1156 bool
1698 Colour3DPlotLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, 1157 Colour3DPlotLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame,
1699 int &resolution, 1158 int &resolution,
1724 Colour3DPlotLayer::toXml(QTextStream &stream, 1183 Colour3DPlotLayer::toXml(QTextStream &stream,
1725 QString indent, QString extraAttributes) const 1184 QString indent, QString extraAttributes) const
1726 { 1185 {
1727 QString s = QString("scale=\"%1\" " 1186 QString s = QString("scale=\"%1\" "
1728 "colourScheme=\"%2\" " 1187 "colourScheme=\"%2\" "
1729 "normalizeColumns=\"%3\" " 1188 "minY=\"%3\" "
1730 "normalizeVisibleArea=\"%4\" " 1189 "maxY=\"%4\" "
1731 "minY=\"%5\" " 1190 "invertVertical=\"%5\" "
1732 "maxY=\"%6\" " 1191 "opaque=\"%6\" %7")
1733 "invertVertical=\"%7\" " 1192 .arg(convertFromColourScale(m_colourScale))
1734 "opaque=\"%8\" %9")
1735 .arg((int)m_colourScale)
1736 .arg(m_colourMap) 1193 .arg(m_colourMap)
1737 .arg(m_normalizeColumns ? "true" : "false")
1738 .arg(m_normalizeVisibleArea ? "true" : "false")
1739 .arg(m_miny) 1194 .arg(m_miny)
1740 .arg(m_maxy) 1195 .arg(m_maxy)
1741 .arg(m_invertVertical ? "true" : "false") 1196 .arg(m_invertVertical ? "true" : "false")
1742 .arg(m_opaque ? "true" : "false") 1197 .arg(m_opaque ? "true" : "false")
1743 .arg(QString("binScale=\"%1\" smooth=\"%2\" gain=\"%3\" ") 1198 .arg(QString("binScale=\"%1\" smooth=\"%2\" gain=\"%3\" ")
1744 .arg((int)m_binScale) 1199 .arg(int(m_binScale))
1745 .arg(m_smooth ? "true" : "false") 1200 .arg(m_smooth ? "true" : "false")
1746 .arg(m_gain)); 1201 .arg(m_gain));
1747 1202
1203 // New-style normalization attributes, allowing for more types of
1204 // normalization in future: write out the column normalization
1205 // type separately, and then whether we are normalizing visible
1206 // area as well afterwards
1207
1208 s += QString("columnNormalization=\"%1\" ")
1209 .arg(m_normalization == ColumnNormalization::Max1 ? "peak" :
1210 m_normalization == ColumnNormalization::Hybrid ? "hybrid" : "none");
1211
1212 // Old-style normalization attribute, for backward compatibility
1213
1214 s += QString("normalizeColumns=\"%1\" ")
1215 .arg(m_normalization == ColumnNormalization::Max1 ? "true" : "false");
1216
1217 // And this applies to both old- and new-style attributes
1218
1219 s += QString("normalizeVisibleArea=\"%1\" ")
1220 .arg(m_normalizeVisibleArea ? "true" : "false");
1221
1748 Layer::toXml(stream, indent, extraAttributes + " " + s); 1222 Layer::toXml(stream, indent, extraAttributes + " " + s);
1749 } 1223 }
1750 1224
1751 void 1225 void
1752 Colour3DPlotLayer::setProperties(const QXmlAttributes &attributes) 1226 Colour3DPlotLayer::setProperties(const QXmlAttributes &attributes)
1753 { 1227 {
1754 bool ok = false, alsoOk = false; 1228 bool ok = false, alsoOk = false;
1755 1229
1756 ColourScale scale = (ColourScale)attributes.value("scale").toInt(&ok); 1230 ColourScaleType colourScale = convertToColourScale
1757 if (ok) setColourScale(scale); 1231 (attributes.value("colourScale").toInt(&ok));
1232 if (ok) setColourScale(colourScale);
1758 1233
1759 int colourMap = attributes.value("colourScheme").toInt(&ok); 1234 int colourMap = attributes.value("colourScheme").toInt(&ok);
1760 if (ok) setColourMap(colourMap); 1235 if (ok) setColourMap(colourMap);
1761 1236
1762 BinScale binscale = (BinScale)attributes.value("binScale").toInt(&ok); 1237 BinScale binScale = (BinScale)
1763 if (ok) setBinScale(binscale); 1238 attributes.value("binScale").toInt(&ok);
1764 1239 if (ok) setBinScale(binScale);
1765 bool normalizeColumns = 1240
1766 (attributes.value("normalizeColumns").trimmed() == "true"); 1241 bool invertVertical =
1767 setNormalizeColumns(normalizeColumns); 1242 (attributes.value("invertVertical").trimmed() == "true");
1768 1243 setInvertVertical(invertVertical);
1244
1245 bool opaque =
1246 (attributes.value("opaque").trimmed() == "true");
1247 setOpaque(opaque);
1248
1249 bool smooth =
1250 (attributes.value("smooth").trimmed() == "true");
1251 setSmooth(smooth);
1252
1253 float gain = attributes.value("gain").toFloat(&ok);
1254 if (ok) setGain(gain);
1255
1256 float min = attributes.value("minY").toFloat(&ok);
1257 float max = attributes.value("maxY").toFloat(&alsoOk);
1258 if (ok && alsoOk) setDisplayExtents(min, max);
1259
1260 bool haveNewStyleNormalization = false;
1261
1262 QString columnNormalization = attributes.value("columnNormalization");
1263
1264 if (columnNormalization != "") {
1265
1266 haveNewStyleNormalization = true;
1267
1268 if (columnNormalization == "peak") {
1269 setNormalization(ColumnNormalization::Max1);
1270 } else if (columnNormalization == "hybrid") {
1271 setNormalization(ColumnNormalization::Hybrid);
1272 } else if (columnNormalization == "none") {
1273 setNormalization(ColumnNormalization::None);
1274 } else {
1275 cerr << "NOTE: Unknown or unsupported columnNormalization attribute \""
1276 << columnNormalization << "\"" << endl;
1277 }
1278 }
1279
1280 if (!haveNewStyleNormalization) {
1281
1282 setNormalization(ColumnNormalization::None);
1283
1284 bool normalizeColumns =
1285 (attributes.value("normalizeColumns").trimmed() == "true");
1286 if (normalizeColumns) {
1287 setNormalization(ColumnNormalization::Max1);
1288 }
1289
1290 bool normalizeHybrid =
1291 (attributes.value("normalizeHybrid").trimmed() == "true");
1292 if (normalizeHybrid) {
1293 setNormalization(ColumnNormalization::Hybrid);
1294 }
1295 }
1296
1769 bool normalizeVisibleArea = 1297 bool normalizeVisibleArea =
1770 (attributes.value("normalizeVisibleArea").trimmed() == "true"); 1298 (attributes.value("normalizeVisibleArea").trimmed() == "true");
1771 setNormalizeVisibleArea(normalizeVisibleArea); 1299 setNormalizeVisibleArea(normalizeVisibleArea);
1772 1300
1773 bool invertVertical = 1301 //!!! todo: check save/reload scaling, compare with
1774 (attributes.value("invertVertical").trimmed() == "true"); 1302 //!!! SpectrogramLayer, compare with prior SV versions, compare
1775 setInvertVertical(invertVertical); 1303 //!!! with Tony v1 and v2 and their save files
1776 1304 }
1777 bool opaque = 1305
1778 (attributes.value("opaque").trimmed() == "true");
1779 setOpaque(opaque);
1780
1781 bool smooth =
1782 (attributes.value("smooth").trimmed() == "true");
1783 setSmooth(smooth);
1784
1785 float gain = attributes.value("gain").toFloat(&ok);
1786 if (ok) setGain(gain);
1787
1788 float min = attributes.value("minY").toFloat(&ok);
1789 float max = attributes.value("maxY").toFloat(&alsoOk);
1790 if (ok && alsoOk) setDisplayExtents(min, max);
1791 }
1792