svgui  1.9
SliceLayer.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7  This file copyright 2006-2007 QMUL.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #include "SliceLayer.h"
17 
18 #include "view/View.h"
19 #include "base/AudioLevel.h"
20 #include "base/RangeMapper.h"
21 #include "base/RealTime.h"
22 #include "ColourMapper.h"
23 #include "ColourDatabase.h"
24 
25 #include "PaintAssistant.h"
26 
27 #include <QPainter>
28 #include <QPainterPath>
29 #include <QTextStream>
30 
31 
33  m_sliceableModel(0),
34  m_colourMap(0),
35  m_energyScale(dBScale),
36  m_samplingMode(SampleMean),
37  m_plotStyle(PlotSteps),
38  m_binScale(LinearBins),
39  m_normalize(false),
40  m_threshold(0.0),
41  m_initialThreshold(0.0),
42  m_gain(1.0),
43  m_currentf0(0),
44  m_currentf1(0)
45 {
46 }
47 
49 {
50 
51 }
52 
53 void
54 SliceLayer::setSliceableModel(const Model *model)
55 {
56  const DenseThreeDimensionalModel *sliceable =
57  dynamic_cast<const DenseThreeDimensionalModel *>(model);
58 
59  if (model && !sliceable) {
60  cerr << "WARNING: SliceLayer::setSliceableModel(" << model
61  << "): model is not a DenseThreeDimensionalModel" << endl;
62  }
63 
64  if (m_sliceableModel == sliceable) return;
65 
66  m_sliceableModel = sliceable;
67 
69 
70  emit modelReplaced();
71 }
72 
73 void
74 SliceLayer::sliceableModelReplaced(const Model *orig, const Model *replacement)
75 {
76  SVDEBUG << "SliceLayer::sliceableModelReplaced(" << orig << ", " << replacement << ")" << endl;
77 
78  if (orig == m_sliceableModel) {
80  (dynamic_cast<const DenseThreeDimensionalModel *>(replacement));
81  }
82 }
83 
84 void
86 {
87  SVDEBUG << "SliceLayer::modelAboutToBeDeleted(" << m << ")" << endl;
88 
89  if (m == m_sliceableModel) {
91  }
92 }
93 
94 QString
96 {
97  int minbin, maxbin, range;
98  return getFeatureDescriptionAux(v, p, true, minbin, maxbin, range);
99 }
100 
101 QString
103  bool includeBinDescription,
104  int &minbin, int &maxbin, int &range) const
105 {
106  minbin = 0;
107  maxbin = 0;
108  if (!m_sliceableModel) return "";
109 
110  int xorigin = m_xorigins[v];
111  int w = v->width() - xorigin - 1;
112 
113  int mh = m_sliceableModel->getHeight();
114  minbin = getBinForX(p.x() - xorigin, mh, w);
115  maxbin = getBinForX(p.x() - xorigin + 1, mh, w);
116 
117  if (minbin >= mh) minbin = mh - 1;
118  if (maxbin >= mh) maxbin = mh - 1;
119  if (minbin < 0) minbin = 0;
120  if (maxbin < 0) maxbin = 0;
121 
122  int sampleRate = m_sliceableModel->getSampleRate();
123 
124  int f0 = m_currentf0;
125  int f1 = m_currentf1;
126 
127  RealTime rt0 = RealTime::frame2RealTime(f0, sampleRate);
128  RealTime rt1 = RealTime::frame2RealTime(f1, sampleRate);
129 
130  range = f1 - f0 + 1;
131 
132  QString rtrangestr = QString("%1 s").arg((rt1 - rt0).toText().c_str());
133 
134  if (includeBinDescription) {
135 
136  float minvalue = 0.f;
137  if (minbin < int(m_values.size())) minvalue = m_values[minbin];
138 
139  float maxvalue = minvalue;
140  if (maxbin < int(m_values.size())) maxvalue = m_values[maxbin];
141 
142  if (minvalue > maxvalue) std::swap(minvalue, maxvalue);
143 
144  QString binstr;
145  if (maxbin != minbin) {
146  binstr = tr("%1 - %2").arg(minbin+1).arg(maxbin+1);
147  } else {
148  binstr = QString("%1").arg(minbin+1);
149  }
150 
151  QString valuestr;
152  if (maxvalue != minvalue) {
153  valuestr = tr("%1 - %2").arg(minvalue).arg(maxvalue);
154  } else {
155  valuestr = QString("%1").arg(minvalue);
156  }
157 
158  QString description = tr("Time:\t%1 - %2\nRange:\t%3 samples (%4)\nBin:\t%5\n%6 value:\t%7")
159  .arg(QString::fromStdString(rt0.toText(true)))
160  .arg(QString::fromStdString(rt1.toText(true)))
161  .arg(range)
162  .arg(rtrangestr)
163  .arg(binstr)
164  .arg(m_samplingMode == NearestSample ? tr("First") :
165  m_samplingMode == SampleMean ? tr("Mean") : tr("Peak"))
166  .arg(valuestr);
167 
168  return description;
169 
170  } else {
171 
172  QString description = tr("Time:\t%1 - %2\nRange:\t%3 samples (%4)")
173  .arg(QString::fromStdString(rt0.toText(true)))
174  .arg(QString::fromStdString(rt1.toText(true)))
175  .arg(range)
176  .arg(rtrangestr);
177 
178  return description;
179  }
180 }
181 
182 float
183 SliceLayer::getXForBin(int bin, int count, float w) const
184 {
185  float x = 0;
186 
187  switch (m_binScale) {
188 
189  case LinearBins:
190  x = (float(w) * bin) / count;
191  break;
192 
193  case LogBins:
194  x = (float(w) * log10f(bin + 1)) / log10f(count + 1);
195  break;
196 
197  case InvertedLogBins:
198  x = w - (float(w) * log10f(count - bin - 1)) / log10f(count);
199  break;
200  }
201 
202  return x;
203 }
204 
205 int
206 SliceLayer::getBinForX(float x, int count, float w) const
207 {
208  int bin = 0;
209 
210  switch (m_binScale) {
211 
212  case LinearBins:
213  bin = int((x * count) / w + 0.0001);
214  break;
215 
216  case LogBins:
217  bin = int(powf(10.f, (x * log10f(count + 1)) / w) - 1 + 0.0001);
218  break;
219 
220  case InvertedLogBins:
221  bin = count + 1 - int(powf(10.f, (log10f(count) * (w - x)) / float(w)) + 0.0001);
222  break;
223  }
224 
225  return bin;
226 }
227 
228 float
229 SliceLayer::getYForValue(float value, const View *v, float &norm) const
230 {
231  norm = 0.f;
232 
233  if (m_yorigins.find(v) == m_yorigins.end()) return 0;
234 
235  value *= m_gain;
236 
237  int yorigin = m_yorigins[v];
238  int h = m_heights[v];
239  float thresh = getThresholdDb();
240 
241  float y = 0.f;
242 
243  if (h <= 0) return y;
244 
245  switch (m_energyScale) {
246 
247  case dBScale:
248  {
249  float db = thresh;
250  if (value > 0.f) db = 10.f * log10f(fabsf(value));
251  if (db < thresh) db = thresh;
252  norm = (db - thresh) / -thresh;
253  y = yorigin - (float(h) * norm);
254  break;
255  }
256 
257  case MeterScale:
258  y = AudioLevel::multiplier_to_preview(value, h);
259  norm = float(y) / float(h);
260  y = yorigin - y;
261  break;
262 
263  case AbsoluteScale:
264  value = fabsf(value);
265  // and fall through
266 
267  case LinearScale:
268  default:
269  norm = (value - m_threshold);
270  if (norm < 0) norm = 0;
271  y = yorigin - (float(h) * norm);
272  break;
273  }
274 
275  return y;
276 }
277 
278 float
279 SliceLayer::getValueForY(float y, const View *v) const
280 {
281  float value = 0.f;
282 
283  if (m_yorigins.find(v) == m_yorigins.end()) return value;
284 
285  int yorigin = m_yorigins[v];
286  int h = m_heights[v];
287  float thresh = getThresholdDb();
288 
289  if (h <= 0) return value;
290 
291  y = yorigin - y;
292 
293  switch (m_energyScale) {
294 
295  case dBScale:
296  {
297  float db = ((y / h) * -thresh) + thresh;
298  value = powf(10.f, db/10.f);
299  break;
300  }
301 
302  case MeterScale:
303  value = AudioLevel::preview_to_multiplier(lrintf(y), h);
304  break;
305 
306  case LinearScale:
307  case AbsoluteScale:
308  default:
309  value = y / h + m_threshold;
310  }
311 
312  return value / m_gain;
313 }
314 
315 void
316 SliceLayer::paint(View *v, QPainter &paint, QRect rect) const
317 {
318  if (!m_sliceableModel || !m_sliceableModel->isOK() ||
319  !m_sliceableModel->isReady()) return;
320 
321  paint.save();
322  paint.setRenderHint(QPainter::Antialiasing, false);
323  paint.setBrush(Qt::NoBrush);
324 
326  if (!m_scalePoints.empty()) {
327  paint.setPen(QColor(240, 240, 240));
328  for (int i = 0; i < (int)m_scalePoints.size(); ++i) {
329  paint.drawLine(0, m_scalePoints[i], rect.width(), m_scalePoints[i]);
330  }
331  }
332  }
333 
334  paint.setPen(getBaseQColor());
335 
336  int xorigin = getVerticalScaleWidth(v, true, paint) + 1;
337  int w = v->width() - xorigin - 1;
338 
339  m_xorigins[v] = xorigin; // for use in getFeatureDescription
340 
341  int yorigin = v->height() - 20 - paint.fontMetrics().height() - 7;
342  int h = yorigin - paint.fontMetrics().height() - 8;
343 
344  m_yorigins[v] = yorigin; // for getYForValue etc
345  m_heights[v] = h;
346 
347  if (h <= 0) return;
348 
349  QPainterPath path;
350 
351  int mh = m_sliceableModel->getHeight();
352 
353  int divisor = 0;
354 
355  m_values.clear();
356  for (int bin = 0; bin < mh; ++bin) {
357  m_values.push_back(0.f);
358  }
359 
360  int f0 = v->getCentreFrame();
361  int f0x = v->getXForFrame(f0);
362  f0 = v->getFrameForX(f0x);
363  int f1 = v->getFrameForX(f0x + 1);
364  if (f1 > f0) --f1;
365 
366 // cerr << "centre frame " << v->getCentreFrame() << ", x " << f0x << ", f0 " << f0 << ", f1 " << f1 << endl;
367 
368  int res = m_sliceableModel->getResolution();
369  int col0 = f0 / res;
370  int col1 = col0;
371  if (m_samplingMode != NearestSample) col1 = f1 / res;
372  f0 = col0 * res;
373  f1 = (col1 + 1) * res - 1;
374 
375 // cerr << "resolution " << res << ", col0 " << col0 << ", col1 " << col1 << ", f0 " << f0 << ", f1 " << f1 << endl;
376 
377  m_currentf0 = f0;
378  m_currentf1 = f1;
379 
380  BiasCurve curve;
381  getBiasCurve(curve);
382  int cs = curve.size();
383 
384  for (int col = col0; col <= col1; ++col) {
385  for (int bin = 0; bin < mh; ++bin) {
386  float value = m_sliceableModel->getValueAt(col, bin);
387  if (bin < cs) value *= curve[bin];
388  if (m_samplingMode == SamplePeak) {
389  if (value > m_values[bin]) m_values[bin] = value;
390  } else {
391  m_values[bin] += value;
392  }
393  }
394  ++divisor;
395  }
396 
397  float max = 0.f;
398  for (int bin = 0; bin < mh; ++bin) {
399  if (m_samplingMode == SampleMean && divisor > 0) {
400  m_values[bin] /= divisor;
401  }
402  if (m_values[bin] > max) max = m_values[bin];
403  }
404  if (max != 0.f && m_normalize) {
405  for (int bin = 0; bin < mh; ++bin) {
406  m_values[bin] /= max;
407  }
408  }
409 
410  float nx = xorigin;
411 
412  ColourMapper mapper(m_colourMap, 0, 1);
413 
414  for (int bin = 0; bin < mh; ++bin) {
415 
416  float x = nx;
417  nx = xorigin + getXForBin(bin + 1, mh, w);
418 
419  float value = m_values[bin];
420  float norm = 0.f;
421  float y = getYForValue(value, v, norm);
422 
423  if (m_plotStyle == PlotLines) {
424 
425  if (bin == 0) {
426  path.moveTo(x, y);
427  } else {
428  path.lineTo(x, y);
429  }
430 
431  } else if (m_plotStyle == PlotSteps) {
432 
433  if (bin == 0) {
434  path.moveTo(x, y);
435  } else {
436  path.lineTo(x, y);
437  }
438  path.lineTo(nx, y);
439 
440  } else if (m_plotStyle == PlotBlocks) {
441 
442  path.moveTo(x, yorigin);
443  path.lineTo(x, y);
444  path.lineTo(nx, y);
445  path.lineTo(nx, yorigin);
446  path.lineTo(x, yorigin);
447 
448  } else if (m_plotStyle == PlotFilledBlocks) {
449 
450  paint.fillRect(QRectF(x, y, nx - x, yorigin - y), mapper.map(norm));
451  }
452 
453  }
454 
455  if (m_plotStyle != PlotFilledBlocks) {
456  paint.drawPath(path);
457  }
458  paint.restore();
459 /*
460  QPoint discard;
461 
462  if (v->getViewManager() && v->getViewManager()->shouldShowFrameCount() &&
463  v->shouldIlluminateLocalFeatures(this, discard)) {
464 
465  int sampleRate = m_sliceableModel->getSampleRate();
466 
467  QString startText = QString("%1 / %2")
468  .arg(QString::fromStdString
469  (RealTime::frame2RealTime
470  (f0, sampleRate).toText(true)))
471  .arg(f0);
472 
473  QString endText = QString(" %1 / %2")
474  .arg(QString::fromStdString
475  (RealTime::frame2RealTime
476  (f1, sampleRate).toText(true)))
477  .arg(f1);
478 
479  QString durationText = QString("(%1 / %2) ")
480  .arg(QString::fromStdString
481  (RealTime::frame2RealTime
482  (f1 - f0 + 1, sampleRate).toText(true)))
483  .arg(f1 - f0 + 1);
484 
485  v->drawVisibleText
486  (paint, xorigin + 5,
487  paint.fontMetrics().ascent() + 5,
488  startText, View::OutlinedText);
489 
490  v->drawVisibleText
491  (paint, xorigin + 5,
492  paint.fontMetrics().ascent() + paint.fontMetrics().height() + 10,
493  endText, View::OutlinedText);
494 
495  v->drawVisibleText
496  (paint, xorigin + 5,
497  paint.fontMetrics().ascent() + 2*paint.fontMetrics().height() + 15,
498  durationText, View::OutlinedText);
499  }
500 */
501 }
502 
503 int
504 SliceLayer::getVerticalScaleWidth(View *, bool, QPainter &paint) const
505 {
507  return std::max(paint.fontMetrics().width("0.0") + 13,
508  paint.fontMetrics().width("x10-10"));
509  } else {
510  return std::max(paint.fontMetrics().width(tr("0dB")),
511  paint.fontMetrics().width(tr("-Inf"))) + 13;
512  }
513 }
514 
515 void
516 SliceLayer::paintVerticalScale(View *v, bool, QPainter &paint, QRect rect) const
517 {
518  float thresh = m_threshold;
520  thresh = AudioLevel::dB_to_multiplier(getThresholdDb());
521  }
522 
523 // int h = (rect.height() * 3) / 4;
524 // int y = (rect.height() / 2) - (h / 2);
525 
526  int yorigin = v->height() - 20 - paint.fontMetrics().height() - 6;
527  int h = yorigin - paint.fontMetrics().height() - 8;
528  if (h < 0) return;
529 
530  QRect actual(rect.x(), rect.y() + yorigin - h, rect.width(), h);
531 
532  int mult = 1;
533 
535  (paint, actual, thresh, 1.0 / m_gain,
537  mult,
538  const_cast<std::vector<int> *>(&m_scalePoints));
539 
540  if (mult != 1 && mult != 0) {
541  int log = lrintf(log10f(mult));
542  QString a = tr("x10");
543  QString b = QString("%1").arg(-log);
544  paint.drawText(3, 8 + paint.fontMetrics().ascent(), a);
545  paint.drawText(3 + paint.fontMetrics().width(a),
546  3 + paint.fontMetrics().ascent(), b);
547  }
548 }
549 
550 Layer::PropertyList
552 {
553  PropertyList list = SingleColourLayer::getProperties();
554  list.push_back("Bin Scale");
555  list.push_back("Plot Type");
556  list.push_back("Scale");
557  list.push_back("Normalize");
558  list.push_back("Threshold");
559  list.push_back("Gain");
560 
561  return list;
562 }
563 
564 QString
565 SliceLayer::getPropertyLabel(const PropertyName &name) const
566 {
567  if (name == "Plot Type") return tr("Plot Type");
568  if (name == "Scale") return tr("Scale");
569  if (name == "Normalize") return tr("Normalize");
570  if (name == "Threshold") return tr("Threshold");
571  if (name == "Gain") return tr("Gain");
572  if (name == "Sampling Mode") return tr("Sampling Mode");
573  if (name == "Bin Scale") return tr("Bin Scale");
575 }
576 
577 QString
578 SliceLayer::getPropertyIconName(const PropertyName &name) const
579 {
580  if (name == "Normalize") return "normalise";
581  return "";
582 }
583 
584 Layer::PropertyType
585 SliceLayer::getPropertyType(const PropertyName &name) const
586 {
587  if (name == "Gain") return RangeProperty;
588  if (name == "Normalize") return ToggleProperty;
589  if (name == "Threshold") return RangeProperty;
590  if (name == "Plot Type") return ValueProperty;
591  if (name == "Scale") return ValueProperty;
592  if (name == "Sampling Mode") return ValueProperty;
593  if (name == "Bin Scale") return ValueProperty;
594  if (name == "Colour" && m_plotStyle == PlotFilledBlocks) return ValueProperty;
596 }
597 
598 QString
599 SliceLayer::getPropertyGroupName(const PropertyName &name) const
600 {
601  if (name == "Scale" ||
602  name == "Normalize" ||
603  name == "Sampling Mode" ||
604  name == "Threshold" ||
605  name == "Gain") return tr("Scale");
606  if (name == "Plot Type" ||
607  name == "Bin Scale") return tr("Bins");
609 }
610 
611 int
612 SliceLayer::getPropertyRangeAndValue(const PropertyName &name,
613  int *min, int *max, int *deflt) const
614 {
615  int val = 0;
616 
617  int garbage0, garbage1, garbage2;
618  if (!min) min = &garbage0;
619  if (!max) max = &garbage1;
620  if (!deflt) deflt = &garbage2;
621 
622  if (name == "Gain") {
623 
624  *min = -50;
625  *max = 50;
626  *deflt = 0;
627 
628  cerr << "gain is " << m_gain << ", mode is " << m_samplingMode << endl;
629 
630  val = lrint(log10(m_gain) * 20.0);
631  if (val < *min) val = *min;
632  if (val > *max) val = *max;
633 
634  } else if (name == "Threshold") {
635 
636  *min = -80;
637  *max = 0;
638 
639  *deflt = lrintf(AudioLevel::multiplier_to_dB(m_initialThreshold));
640  if (*deflt < *min) *deflt = *min;
641  if (*deflt > *max) *deflt = *max;
642 
643  val = lrintf(AudioLevel::multiplier_to_dB(m_threshold));
644  if (val < *min) val = *min;
645  if (val > *max) val = *max;
646 
647  } else if (name == "Normalize") {
648 
649  val = (m_normalize ? 1 : 0);
650  *deflt = 0;
651 
652  } else if (name == "Colour" && m_plotStyle == PlotFilledBlocks) {
653 
654  *min = 0;
655  *max = ColourMapper::getColourMapCount() - 1;
656  *deflt = 0;
657 
658  val = m_colourMap;
659 
660  } else if (name == "Scale") {
661 
662  *min = 0;
663  *max = 3;
664  *deflt = (int)dBScale;
665 
666  val = (int)m_energyScale;
667 
668  } else if (name == "Sampling Mode") {
669 
670  *min = 0;
671  *max = 2;
672  *deflt = (int)SampleMean;
673 
674  val = (int)m_samplingMode;
675 
676  } else if (name == "Plot Type") {
677 
678  *min = 0;
679  *max = 3;
680  *deflt = (int)PlotSteps;
681 
682  val = (int)m_plotStyle;
683 
684  } else if (name == "Bin Scale") {
685 
686  *min = 0;
687  *max = 2;
688  *deflt = (int)LinearBins;
689 // *max = 1; // I don't think we really do want to offer inverted log
690 
691  val = (int)m_binScale;
692 
693  } else {
694  val = SingleColourLayer::getPropertyRangeAndValue(name, min, max, deflt);
695  }
696 
697  return val;
698 }
699 
700 QString
701 SliceLayer::getPropertyValueLabel(const PropertyName &name,
702  int value) const
703 {
704  if (name == "Colour" && m_plotStyle == PlotFilledBlocks) {
705  return ColourMapper::getColourMapName(value);
706  }
707  if (name == "Scale") {
708  switch (value) {
709  default:
710  case 0: return tr("Linear");
711  case 1: return tr("Meter");
712  case 2: return tr("Log");
713  case 3: return tr("Absolute");
714  }
715  }
716  if (name == "Sampling Mode") {
717  switch (value) {
718  default:
719  case 0: return tr("Any");
720  case 1: return tr("Mean");
721  case 2: return tr("Peak");
722  }
723  }
724  if (name == "Plot Type") {
725  switch (value) {
726  default:
727  case 0: return tr("Lines");
728  case 1: return tr("Steps");
729  case 2: return tr("Blocks");
730  case 3: return tr("Colours");
731  }
732  }
733  if (name == "Bin Scale") {
734  switch (value) {
735  default:
736  case 0: return tr("Linear");
737  case 1: return tr("Log");
738  case 2: return tr("Rev Log");
739  }
740  }
741  return SingleColourLayer::getPropertyValueLabel(name, value);
742 }
743 
744 RangeMapper *
745 SliceLayer::getNewPropertyRangeMapper(const PropertyName &name) const
746 {
747  if (name == "Gain") {
748  return new LinearRangeMapper(-50, 50, -25, 25, tr("dB"));
749  }
750  if (name == "Threshold") {
751  return new LinearRangeMapper(-80, 0, -80, 0, tr("dB"));
752  }
754 }
755 
756 void
757 SliceLayer::setProperty(const PropertyName &name, int value)
758 {
759  if (name == "Gain") {
760  setGain(pow(10, float(value)/20.0));
761  } else if (name == "Threshold") {
762  if (value == -80) setThreshold(0.0);
763  else setThreshold(AudioLevel::dB_to_multiplier(value));
764  } else if (name == "Colour" && m_plotStyle == PlotFilledBlocks) {
765  setFillColourMap(value);
766  } else if (name == "Scale") {
767  switch (value) {
768  default:
769  case 0: setEnergyScale(LinearScale); break;
770  case 1: setEnergyScale(MeterScale); break;
771  case 2: setEnergyScale(dBScale); break;
772  case 3: setEnergyScale(AbsoluteScale); break;
773  }
774  } else if (name == "Plot Type") {
775  setPlotStyle(PlotStyle(value));
776  } else if (name == "Sampling Mode") {
777  switch (value) {
778  default:
779  case 0: setSamplingMode(NearestSample); break;
780  case 1: setSamplingMode(SampleMean); break;
781  case 2: setSamplingMode(SamplePeak); break;
782  }
783  } else if (name == "Bin Scale") {
784  switch (value) {
785  default:
786  case 0: setBinScale(LinearBins); break;
787  case 1: setBinScale(LogBins); break;
788  case 2: setBinScale(InvertedLogBins); break;
789  }
790  } else if (name == "Normalize") {
791  setNormalize(value ? true : false);
792  } else {
793  SingleColourLayer::setProperty(name, value);
794  }
795 }
796 
797 void
799 {
800  if (m_colourMap == map) return;
801  m_colourMap = map;
802  emit layerParametersChanged();
803 }
804 
805 void
807 {
808  if (m_energyScale == scale) return;
809  m_energyScale = scale;
810  emit layerParametersChanged();
811 }
812 
813 void
815 {
816  if (m_samplingMode == mode) return;
817  m_samplingMode = mode;
818  emit layerParametersChanged();
819 }
820 
821 void
823 {
824  if (m_plotStyle == style) return;
825  bool colourTypeChanged = (style == PlotFilledBlocks ||
827  m_plotStyle = style;
828  if (colourTypeChanged) {
830  }
831  emit layerParametersChanged();
832 }
833 
834 void
836 {
837  if (m_binScale == scale) return;
838  m_binScale = scale;
839  emit layerParametersChanged();
840 }
841 
842 void
844 {
845  if (m_normalize == n) return;
846  m_normalize = n;
847  emit layerParametersChanged();
848 }
849 
850 void
852 {
853  if (m_threshold == thresh) return;
854  m_threshold = thresh;
855  emit layerParametersChanged();
856 }
857 
858 void
860 {
861  if (m_gain == gain) return;
862  m_gain = gain;
863  emit layerParametersChanged();
864 }
865 
866 float
868 {
869  if (m_threshold == 0.0) return -80.f;
870  float db = AudioLevel::multiplier_to_dB(m_threshold);
871  return db;
872 }
873 
874 int
875 SliceLayer::getDefaultColourHint(bool darkbg, bool &impose)
876 {
877  impose = false;
879  (QString(darkbg ? "Bright Blue" : "Blue"));
880 }
881 
882 void
883 SliceLayer::toXml(QTextStream &stream,
884  QString indent, QString extraAttributes) const
885 {
886  QString s;
887 
888  s += QString("colourScheme=\"%1\" "
889  "energyScale=\"%2\" "
890  "samplingMode=\"%3\" "
891  "plotStyle=\"%4\" "
892  "binScale=\"%5\" "
893  "gain=\"%6\" "
894  "threshold=\"%7\" "
895  "normalize=\"%8\"")
896  .arg(m_colourMap)
897  .arg(m_energyScale)
898  .arg(m_samplingMode)
899  .arg(m_plotStyle)
900  .arg(m_binScale)
901  .arg(m_gain)
902  .arg(m_threshold)
903  .arg(m_normalize ? "true" : "false");
904 
905  SingleColourLayer::toXml(stream, indent, extraAttributes + " " + s);
906 }
907 
908 void
909 SliceLayer::setProperties(const QXmlAttributes &attributes)
910 {
911  bool ok = false;
912 
914 
915  EnergyScale scale = (EnergyScale)
916  attributes.value("energyScale").toInt(&ok);
917  if (ok) setEnergyScale(scale);
918 
919  SamplingMode mode = (SamplingMode)
920  attributes.value("samplingMode").toInt(&ok);
921  if (ok) setSamplingMode(mode);
922 
923  int colourMap = attributes.value("colourScheme").toInt(&ok);
924  if (ok) setFillColourMap(colourMap);
925 
926  PlotStyle s = (PlotStyle)
927  attributes.value("plotStyle").toInt(&ok);
928  if (ok) setPlotStyle(s);
929 
930  BinScale b = (BinScale)
931  attributes.value("binScale").toInt(&ok);
932  if (ok) setBinScale(b);
933 
934  float gain = attributes.value("gain").toFloat(&ok);
935  if (ok) setGain(gain);
936 
937  float threshold = attributes.value("threshold").toFloat(&ok);
938  if (ok) setThreshold(threshold);
939 
940  bool normalize = (attributes.value("normalize").trimmed() == "true");
941  setNormalize(normalize);
942 }
943 
944 bool
945 SliceLayer::getValueExtents(float &, float &, bool &, QString &) const
946 {
947  return false;
948 }
949 
int getFrameForX(int x) const
Return the closest frame to the given pixel x-coordinate.
Definition: View.cpp:363
EnergyScale m_energyScale
Definition: SliceLayer.h:135
virtual QString getPropertyLabel(const PropertyName &) const
Definition: SliceLayer.cpp:565
virtual QString getPropertyIconName(const PropertyName &) const
Definition: SliceLayer.cpp:578
int m_currentf0
Definition: SliceLayer.h:147
virtual QString getFeatureDescriptionAux(View *v, QPoint &, bool includeBinDescription, int &minbin, int &maxbin, int &range) const
Definition: SliceLayer.cpp:102
virtual float getXForBin(int bin, int totalBins, float w) const
Definition: SliceLayer.cpp:183
void setFillColourMap(int)
Definition: SliceLayer.cpp:798
void connectSignals(const Model *)
Definition: Layer.cpp:49
virtual QString getPropertyValueLabel(const PropertyName &, int value) const
Definition: SliceLayer.cpp:701
virtual PropertyType getPropertyType(const PropertyName &) const
Definition: SliceLayer.cpp:585
virtual float getYForValue(float value, const View *v, float &norm) const
Definition: SliceLayer.cpp:229
int m_currentf1
Definition: SliceLayer.h:148
void modelReplaced()
float m_initialThreshold
Definition: SliceLayer.h:141
std::map< const View *, int > m_heights
Definition: SliceLayer.h:146
virtual void paintVerticalScale(View *v, bool, QPainter &paint, QRect rect) const
Definition: SliceLayer.cpp:516
void setSamplingMode(SamplingMode)
Definition: SliceLayer.cpp:814
std::map< const View *, int > m_xorigins
Definition: SliceLayer.h:144
const DenseThreeDimensionalModel * m_sliceableModel
Definition: SliceLayer.h:133
virtual void toXml(QTextStream &stream, QString indent="", QString extraAttributes="") const
Convert the layer's data (though not those of the model it refers to) into XML for file output.
virtual ViewManager * getViewManager() const
Definition: View.h:233
virtual QString getPropertyGroupName(const PropertyName &) const
Definition: SliceLayer.cpp:599
void setThreshold(float)
Definition: SliceLayer.cpp:851
virtual void setProperties(const QXmlAttributes &)
Set the particular properties of a layer (those specific to the subclass) from a set of XML attribute...
Definition: SliceLayer.cpp:909
static int getColourMapCount()
void sliceableModelReplaced(const Model *, const Model *)
Definition: SliceLayer.cpp:74
virtual void setProperty(const PropertyName &, int value)
Definition: SliceLayer.cpp:757
std::vector< int > m_scalePoints
Definition: SliceLayer.h:143
void layerParameterRangesChanged()
virtual QColor getBaseQColor() const
PlotStyle m_plotStyle
Definition: SliceLayer.h:137
bool shouldShowScaleGuides() const
Definition: ViewManager.h:217
virtual int getPropertyRangeAndValue(const PropertyName &, int *min, int *max, int *deflt) const
Definition: SliceLayer.cpp:612
int m_colourMap
Definition: SliceLayer.h:134
BinScale m_binScale
Definition: SliceLayer.h:138
int getColourIndex(QString name) const
virtual int getDefaultColourHint(bool dark, bool &impose)
Definition: SliceLayer.cpp:875
virtual QString getPropertyLabel(const PropertyName &) const
virtual QString getFeatureDescription(View *v, QPoint &) const
Definition: SliceLayer.cpp:95
void setNormalize(bool n)
Definition: SliceLayer.cpp:843
virtual int getBinForX(float x, int totalBins, float w) const
Definition: SliceLayer.cpp:206
virtual PropertyList getProperties() const
Definition: SliceLayer.cpp:551
void setSliceableModel(const Model *model)
Definition: SliceLayer.cpp:54
void layerParametersChanged()
virtual float getValueForY(float y, const View *v) const
Definition: SliceLayer.cpp:279
bool m_normalize
Definition: SliceLayer.h:139
virtual QString getPropertyGroupName(const PropertyName &) const
std::vector< float > m_values
Definition: SliceLayer.h:149
virtual float getThresholdDb() const
Definition: SliceLayer.cpp:867
virtual void setProperties(const QXmlAttributes &attributes)
Set the particular properties of a layer (those specific to the subclass) from a set of XML attribute...
virtual int getPropertyRangeAndValue(const PropertyName &, int *min, int *max, int *deflt) const
virtual void getBiasCurve(BiasCurve &) const
Definition: SliceLayer.h:127
A class for mapping intensity values onto various colour maps.
Definition: ColourMapper.h:27
QColor map(float value) const
void setPlotStyle(PlotStyle style)
Definition: SliceLayer.cpp:822
virtual RangeMapper * getNewPropertyRangeMapper(const PropertyName &) const
Definition: SliceLayer.cpp:745
virtual RangeMapper * getNewPropertyRangeMapper(const PropertyName &) const
void setBinScale(BinScale scale)
Definition: SliceLayer.cpp:835
float m_threshold
Definition: SliceLayer.h:140
void setGain(float gain)
Definition: SliceLayer.cpp:859
std::vector< float > BiasCurve
Definition: SliceLayer.h:126
View is the base class of widgets that display one or more overlaid views of data against a horizonta...
Definition: View.h:50
void setEnergyScale(EnergyScale)
Definition: SliceLayer.cpp:806
std::map< const View *, int > m_yorigins
Definition: SliceLayer.h:145
static void paintVerticalLevelScale(QPainter &p, QRect rect, float minVal, float maxVal, Scale scale, int &multRtn, std::vector< int > *markCoordRtns=0)
virtual QString getPropertyValueLabel(const PropertyName &, int value) const
SamplingMode m_samplingMode
Definition: SliceLayer.h:136
int getCentreFrame() const
Return the centre frame of the visible widget.
Definition: View.h:81
virtual bool getValueExtents(float &min, float &max, bool &logarithmic, QString &unit) const
Return the minimum and maximum values for the y axis of the model in this layer, as well as whether t...
Definition: SliceLayer.cpp:945
virtual void paint(View *v, QPainter &paint, QRect rect) const
Paint the given rectangle of this layer onto the given view using the given painter,...
Definition: SliceLayer.cpp:316
virtual PropertyList getProperties() const
float m_gain
Definition: SliceLayer.h:142
virtual int getVerticalScaleWidth(View *v, bool, QPainter &) const
Definition: SliceLayer.cpp:504
void modelAboutToBeDeleted(Model *)
Definition: SliceLayer.cpp:85
virtual void toXml(QTextStream &stream, QString indent="", QString extraAttributes="") const
Convert the layer's data (though not those of the model it refers to) into XML for file output.
Definition: SliceLayer.cpp:883
virtual PropertyType getPropertyType(const PropertyName &) const
int getXForFrame(int frame) const
Return the pixel x-coordinate corresponding to a given sample frame (which may be negative).
Definition: View.cpp:357
static ColourDatabase * getInstance()
virtual void setProperty(const PropertyName &, int value)
static QString getColourMapName(int n)