Mercurial > hg > svgui
comparison layer/SliceLayer.cpp @ 198:c2ed5014d4ff
* Scale fixes and feature descriptions in slice layer
author | Chris Cannam |
---|---|
date | Thu, 01 Feb 2007 16:54:42 +0000 |
parents | 6b023411087b |
children | 45e995ed84d9 |
comparison
equal
deleted
inserted
replaced
197:6b023411087b | 198:c2ed5014d4ff |
---|---|
30 SliceLayer::SliceLayer() : | 30 SliceLayer::SliceLayer() : |
31 m_sliceableModel(0), | 31 m_sliceableModel(0), |
32 m_colour(Qt::darkBlue), | 32 m_colour(Qt::darkBlue), |
33 m_colourMap(0), | 33 m_colourMap(0), |
34 m_energyScale(dBScale), | 34 m_energyScale(dBScale), |
35 m_samplingMode(SamplePeak), | 35 m_samplingMode(SampleMean), |
36 m_plotStyle(PlotSteps), | 36 m_plotStyle(PlotSteps), |
37 m_binScale(LinearBins), | 37 m_binScale(LinearBins), |
38 m_normalize(false), | 38 m_normalize(false), |
39 m_bias(false), | 39 m_bias(false), |
40 m_gain(1.0) | 40 m_gain(1.0), |
41 m_currentf0(0), | |
42 m_currentf1(0) | |
41 { | 43 { |
42 } | 44 } |
43 | 45 |
44 SliceLayer::~SliceLayer() | 46 SliceLayer::~SliceLayer() |
45 { | 47 { |
90 std::cerr << "SliceLayer::modelAboutToBeDeleted(" << m << ")" << std::endl; | 92 std::cerr << "SliceLayer::modelAboutToBeDeleted(" << m << ")" << std::endl; |
91 | 93 |
92 if (m == m_sliceableModel) { | 94 if (m == m_sliceableModel) { |
93 setSliceableModel(0); | 95 setSliceableModel(0); |
94 } | 96 } |
97 } | |
98 | |
99 QString | |
100 SliceLayer::getFeatureDescription(View *v, QPoint &p) const | |
101 { | |
102 if (!m_sliceableModel) return ""; | |
103 | |
104 int xorigin = m_xorigins[v]; | |
105 int w = v->width() - xorigin - 1; | |
106 | |
107 int mh = m_sliceableModel->getHeight(); | |
108 int bin = getBinForX(p.x() - xorigin, mh, w); | |
109 if (bin >= mh) bin = mh - 1; | |
110 if (bin < 0) bin = 0; | |
111 | |
112 int sampleRate = m_sliceableModel->getSampleRate(); | |
113 | |
114 size_t f0 = m_currentf0; | |
115 size_t f1 = m_currentf1; | |
116 | |
117 RealTime rt0 = RealTime::frame2RealTime(f0, sampleRate); | |
118 RealTime rt1 = RealTime::frame2RealTime(f1, sampleRate); | |
119 | |
120 size_t range = f1 - f0 + 1; | |
121 | |
122 float value = 0.f; | |
123 if (bin < m_values.size()) value = m_values[bin]; | |
124 | |
125 QString description = tr("Time:\t%1 - %2\nRange:\t%3 samples\nBin:\t%4\n%5 value:\t%6") | |
126 .arg(QString::fromStdString(rt0.toText(true))) | |
127 .arg(QString::fromStdString(rt1.toText(true))) | |
128 .arg(range) | |
129 .arg(bin + 1) | |
130 .arg(m_samplingMode == NearestSample ? tr("First") : | |
131 m_samplingMode == SampleMean ? tr("Mean") : tr("Peak")) | |
132 .arg(value); | |
133 | |
134 return description; | |
135 } | |
136 | |
137 float | |
138 SliceLayer::getXForBin(int bin, int count, float w) const | |
139 { | |
140 float x = 0; | |
141 | |
142 switch (m_binScale) { | |
143 | |
144 case LinearBins: | |
145 x = (float(w) * bin) / count; | |
146 break; | |
147 | |
148 case LogBins: | |
149 x = (float(w) * log10f(bin + 1)) / log10f(count + 1); | |
150 break; | |
151 | |
152 case InvertedLogBins: | |
153 x = w - (float(w) * log10f(count - bin - 1)) / log10f(count); | |
154 break; | |
155 } | |
156 | |
157 return x; | |
158 } | |
159 | |
160 int | |
161 SliceLayer::getBinForX(float x, int count, float w) const | |
162 { | |
163 int bin = 0; | |
164 | |
165 switch (m_binScale) { | |
166 | |
167 case LinearBins: | |
168 bin = int((x * count) / w + 0.0001); | |
169 break; | |
170 | |
171 case LogBins: | |
172 bin = int(powf(10.f, (x * log10f(count + 1)) / w) - 1 + 0.0001); | |
173 break; | |
174 | |
175 case InvertedLogBins: | |
176 bin = count + 1 - int(powf(10.f, (log10f(count) * (w - x)) / float(w)) + 0.0001); | |
177 break; | |
178 } | |
179 | |
180 return bin; | |
95 } | 181 } |
96 | 182 |
97 void | 183 void |
98 SliceLayer::paint(View *v, QPainter &paint, QRect rect) const | 184 SliceLayer::paint(View *v, QPainter &paint, QRect rect) const |
99 { | 185 { |
114 paint.setPen(m_colour); | 200 paint.setPen(m_colour); |
115 | 201 |
116 // int w = (v->width() * 2) / 3; | 202 // int w = (v->width() * 2) / 3; |
117 int xorigin = getVerticalScaleWidth(v, paint) + 1; //!!! (v->width() / 2) - (w / 2); | 203 int xorigin = getVerticalScaleWidth(v, paint) + 1; //!!! (v->width() / 2) - (w / 2); |
118 int w = v->width() - xorigin - 1; | 204 int w = v->width() - xorigin - 1; |
205 | |
206 m_xorigins[v] = xorigin; // for use in getFeatureDescription | |
119 | 207 |
120 int yorigin = v->height() - 20 - paint.fontMetrics().height() - 7; | 208 int yorigin = v->height() - 20 - paint.fontMetrics().height() - 7; |
121 int h = yorigin - paint.fontMetrics().height() - 8; | 209 int h = yorigin - paint.fontMetrics().height() - 8; |
122 if (h < 0) return; | 210 if (h < 0) return; |
123 | 211 |
127 QPainterPath path; | 215 QPainterPath path; |
128 float thresh = -80.f; | 216 float thresh = -80.f; |
129 | 217 |
130 int mh = m_sliceableModel->getHeight(); | 218 int mh = m_sliceableModel->getHeight(); |
131 | 219 |
132 float *values = new float[mh]; | |
133 int divisor = 0; | 220 int divisor = 0; |
134 | 221 |
222 m_values.clear(); | |
135 for (size_t bin = 0; bin < mh; ++bin) { | 223 for (size_t bin = 0; bin < mh; ++bin) { |
136 values[bin] = 0.f; | 224 m_values.push_back(0.f); |
137 } | 225 } |
138 | 226 |
139 size_t f0 = v->getCentreFrame(); | 227 size_t f0 = v->getCentreFrame(); |
140 int f0x = v->getXForFrame(f0); | 228 int f0x = v->getXForFrame(f0); |
141 f0 = v->getFrameForX(f0x); | 229 f0 = v->getFrameForX(f0x); |
148 col1 = f1 / m_sliceableModel->getResolution(); | 236 col1 = f1 / m_sliceableModel->getResolution(); |
149 } | 237 } |
150 f0 = col0 * m_sliceableModel->getResolution(); | 238 f0 = col0 * m_sliceableModel->getResolution(); |
151 f1 = (col1 + 1) * m_sliceableModel->getResolution() - 1; | 239 f1 = (col1 + 1) * m_sliceableModel->getResolution() - 1; |
152 | 240 |
241 m_currentf0 = f0; | |
242 m_currentf1 = f1; | |
243 | |
153 for (size_t col = col0; col <= col1; ++col) { | 244 for (size_t col = col0; col <= col1; ++col) { |
154 for (size_t bin = 0; bin < mh; ++bin) { | 245 for (size_t bin = 0; bin < mh; ++bin) { |
155 float value = m_sliceableModel->getValueAt(col, bin); | 246 float value = m_sliceableModel->getValueAt(col, bin); |
156 if (m_bias) value *= bin + 1; | 247 if (m_bias) value *= bin + 1; |
157 if (m_samplingMode == SamplePeak) { | 248 if (m_samplingMode == SamplePeak) { |
158 if (value > values[bin]) values[bin] = value; | 249 if (value > m_values[bin]) m_values[bin] = value; |
159 } else { | 250 } else { |
160 values[bin] += value; | 251 m_values[bin] += value; |
161 } | 252 } |
162 } | 253 } |
163 ++divisor; | 254 ++divisor; |
164 } | 255 } |
165 | 256 |
166 float max = 0.f; | 257 float max = 0.f; |
167 for (size_t bin = 0; bin < mh; ++bin) { | 258 for (size_t bin = 0; bin < mh; ++bin) { |
168 if (m_samplingMode == SampleMean) values[bin] /= divisor; | 259 if (m_samplingMode == SampleMean) m_values[bin] /= divisor; |
169 if (values[bin] > max) max = values[bin]; | 260 if (m_values[bin] > max) max = m_values[bin]; |
170 } | 261 } |
171 if (max != 0.f && m_normalize) { | 262 if (max != 0.f && m_normalize) { |
172 for (size_t bin = 0; bin < mh; ++bin) { | 263 for (size_t bin = 0; bin < mh; ++bin) { |
173 values[bin] /= max; | 264 m_values[bin] /= max; |
174 } | 265 } |
175 } | 266 } |
176 | 267 |
177 float py = 0; | 268 float py = 0; |
178 float nx = xorigin; | 269 float nx = xorigin; |
179 | 270 |
180 ColourMapper mapper(m_colourMap, 0, 1); | 271 ColourMapper mapper(m_colourMap, 0, 1); |
181 | 272 |
182 for (size_t bin = 0; bin < mh; ++bin) { | 273 for (size_t bin = 0; bin < mh; ++bin) { |
183 | 274 |
184 float x; | 275 float x = nx; |
185 | 276 nx = xorigin + getXForBin(bin + 1, mh, w); |
186 switch (m_binScale) { | 277 |
187 | 278 float value = m_values[bin]; |
188 case LinearBins: | |
189 x = nx; | |
190 nx = xorigin + (float(w) * (bin + 1)) / mh; | |
191 break; | |
192 | |
193 case LogBins: | |
194 x = nx; | |
195 nx = xorigin + (float(w) * (log10f(bin + 2) - log10f(1))) / | |
196 (log10f(mh + 1) - log10f(1)); | |
197 break; | |
198 | |
199 case InvertedLogBins: | |
200 x = nx; | |
201 nx = xorigin + w - (float(w) * (log10f(mh - bin) - log10f(1))) / | |
202 (log10f(mh) - log10f(1)); | |
203 break; | |
204 } | |
205 | |
206 float value = values[bin]; | |
207 | 279 |
208 value *= m_gain; | 280 value *= m_gain; |
209 float norm = 0.f; | 281 float norm = 0.f; |
210 float y = 0.f; | 282 float y = 0.f; |
211 | 283 |
268 | 340 |
269 if (m_plotStyle != PlotFilledBlocks) { | 341 if (m_plotStyle != PlotFilledBlocks) { |
270 paint.drawPath(path); | 342 paint.drawPath(path); |
271 } | 343 } |
272 paint.restore(); | 344 paint.restore(); |
273 | 345 /* |
274 QPoint discard; | 346 QPoint discard; |
275 | 347 |
276 if (v->getViewManager() && v->getViewManager()->shouldShowFrameCount() && | 348 if (v->getViewManager() && v->getViewManager()->shouldShowFrameCount() && |
277 v->shouldIlluminateLocalFeatures(this, discard)) { | 349 v->shouldIlluminateLocalFeatures(this, discard)) { |
278 | 350 |
309 v->drawVisibleText | 381 v->drawVisibleText |
310 (paint, xorigin + 5, | 382 (paint, xorigin + 5, |
311 paint.fontMetrics().ascent() + 2*paint.fontMetrics().height() + 15, | 383 paint.fontMetrics().ascent() + 2*paint.fontMetrics().height() + 15, |
312 durationText, View::OutlinedText); | 384 durationText, View::OutlinedText); |
313 } | 385 } |
314 | |
315 /* | |
316 | |
317 QString frameRange; | |
318 if (f1 != f0) { | |
319 frameRange = QString("%1 - %2").arg(f0).arg(f1); | |
320 } else { | |
321 frameRange = QString("%1").arg(f0); | |
322 } | |
323 | |
324 QString colRange; | |
325 if (col1 != col0) { | |
326 colRange = tr("%1 hops").arg(col1 - col0 + 1); | |
327 } else { | |
328 colRange = tr("1 hop"); | |
329 } | |
330 | |
331 if (v->getViewManager() && v->getViewManager()->shouldShowFrameCount()) { | |
332 | |
333 v->drawVisibleText | |
334 (paint, xorigin + 5, | |
335 paint.fontMetrics().ascent() + 5, | |
336 frameRange, View::OutlinedText); | |
337 | |
338 v->drawVisibleText | |
339 (paint, xorigin + 5, | |
340 paint.fontMetrics().ascent() + paint.fontMetrics().height() + 10, | |
341 colRange, View::OutlinedText); | |
342 } | |
343 */ | 386 */ |
344 } | 387 } |
345 | 388 |
346 int | 389 int |
347 SliceLayer::getVerticalScaleWidth(View *v, QPainter &paint) const | 390 SliceLayer::getVerticalScaleWidth(View *v, QPainter &paint) const |
381 SliceLayer::getProperties() const | 424 SliceLayer::getProperties() const |
382 { | 425 { |
383 PropertyList list; | 426 PropertyList list; |
384 list.push_back("Colour"); | 427 list.push_back("Colour"); |
385 list.push_back("Plot Type"); | 428 list.push_back("Plot Type"); |
386 list.push_back("Sampling Mode"); | 429 // list.push_back("Sampling Mode"); |
387 list.push_back("Scale"); | 430 list.push_back("Scale"); |
388 list.push_back("Normalize"); | 431 list.push_back("Normalize"); |
389 list.push_back("Gain"); | 432 list.push_back("Gain"); |
390 list.push_back("Bin Scale"); | 433 list.push_back("Bin Scale"); |
391 | 434 |
494 deft = (int)m_plotStyle; | 537 deft = (int)m_plotStyle; |
495 | 538 |
496 } else if (name == "Bin Scale") { | 539 } else if (name == "Bin Scale") { |
497 | 540 |
498 *min = 0; | 541 *min = 0; |
499 // *max = 2; | 542 *max = 2; |
500 *max = 1; // I don't think we really do want to offer inverted log | 543 // *max = 1; // I don't think we really do want to offer inverted log |
501 | 544 |
502 deft = (int)m_binScale; | 545 deft = (int)m_binScale; |
503 | 546 |
504 } else { | 547 } else { |
505 deft = Layer::getPropertyRangeAndValue(name, min, max); | 548 deft = Layer::getPropertyRangeAndValue(name, min, max); |
553 } | 596 } |
554 } | 597 } |
555 if (name == "Bin Scale") { | 598 if (name == "Bin Scale") { |
556 switch (value) { | 599 switch (value) { |
557 default: | 600 default: |
558 case 0: return tr("Linear"); | 601 case 0: return tr("Linear Bins"); |
559 case 1: return tr("Log"); | 602 case 1: return tr("Log Bins"); |
560 case 2: return tr("Rev Log"); | 603 case 2: return tr("Rev Log Bins"); |
561 } | 604 } |
562 } | 605 } |
563 return tr("<unknown>"); | 606 return tr("<unknown>"); |
564 } | 607 } |
565 | 608 |