comparison layer/SliceLayer.cpp @ 1486:ac0a8addabcf

Merge from branch by-id
author Chris Cannam
date Wed, 17 Jul 2019 14:25:16 +0100
parents 0e971e3d93e2
children
comparison
equal deleted inserted replaced
1468:de41a11cabc2 1486:ac0a8addabcf
30 #include <QPainterPath> 30 #include <QPainterPath>
31 #include <QTextStream> 31 #include <QTextStream>
32 32
33 33
34 SliceLayer::SliceLayer() : 34 SliceLayer::SliceLayer() :
35 m_sliceableModel(nullptr),
36 m_binAlignment(BinsSpanScalePoints), 35 m_binAlignment(BinsSpanScalePoints),
37 m_colourMap(int(ColourMapper::Ice)), 36 m_colourMap(int(ColourMapper::Ice)),
38 m_colourInverted(false), 37 m_colourInverted(false),
39 m_energyScale(dBScale), 38 m_energyScale(dBScale),
40 m_samplingMode(SampleMean), 39 m_samplingMode(SampleMean),
55 { 54 {
56 55
57 } 56 }
58 57
59 void 58 void
60 SliceLayer::setSliceableModel(const Model *model) 59 SliceLayer::setSliceableModel(ModelId modelId)
61 { 60 {
62 const DenseThreeDimensionalModel *sliceable = 61 auto newModel = ModelById::getAs<DenseThreeDimensionalModel>(modelId);
63 dynamic_cast<const DenseThreeDimensionalModel *>(model); 62
64 63 if (!modelId.isNone() && !newModel) {
65 if (model && !sliceable) { 64 throw std::logic_error("Not a DenseThreeDimensionalModel");
66 cerr << "WARNING: SliceLayer::setSliceableModel(" << model 65 }
67 << "): model is not a DenseThreeDimensionalModel" << endl; 66
68 } 67 if (m_sliceableModel == modelId) return;
69 68 m_sliceableModel = modelId;
70 if (m_sliceableModel == sliceable) return; 69
71 70 if (newModel) {
72 m_sliceableModel = sliceable; 71 connectSignals(m_sliceableModel);
73 72
74 if (!m_sliceableModel) return; 73 if (m_minbin == 0 && m_maxbin == 0) {
75 74 m_minbin = 0;
76 connectSignals(m_sliceableModel); 75 m_maxbin = newModel->getHeight();
77 76 }
78 if (m_minbin == 0 && m_maxbin == 0) {
79 m_minbin = 0;
80 m_maxbin = m_sliceableModel->getHeight();
81 } 77 }
82 78
83 emit modelReplaced(); 79 emit modelReplaced();
84 emit layerParametersChanged(); 80 emit layerParametersChanged();
85 } 81 }
86 82
87 void 83 void
88 SliceLayer::sliceableModelReplaced(const Model *orig, const Model *replacement) 84 SliceLayer::sliceableModelReplaced(ModelId orig, ModelId replacement)
89 { 85 {
90 SVDEBUG << "SliceLayer::sliceableModelReplaced(" << orig << ", " << replacement << ")" << endl; 86 SVDEBUG << "SliceLayer::sliceableModelReplaced(" << orig << ", " << replacement << ")" << endl;
91 87
92 if (orig == m_sliceableModel) { 88 if (orig == m_sliceableModel) {
93 setSliceableModel 89 setSliceableModel(replacement);
94 (dynamic_cast<const DenseThreeDimensionalModel *>(replacement));
95 }
96 }
97
98 void
99 SliceLayer::modelAboutToBeDeleted(Model *m)
100 {
101 SVDEBUG << "SliceLayer::modelAboutToBeDeleted(" << m << ")" << endl;
102
103 if (m == m_sliceableModel) {
104 setSliceableModel(nullptr);
105 } 90 }
106 } 91 }
107 92
108 QString 93 QString
109 SliceLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &p) const 94 SliceLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &p) const
117 bool includeBinDescription, 102 bool includeBinDescription,
118 int &minbin, int &maxbin, int &range) const 103 int &minbin, int &maxbin, int &range) const
119 { 104 {
120 minbin = 0; 105 minbin = 0;
121 maxbin = 0; 106 maxbin = 0;
122 if (!m_sliceableModel) return ""; 107
108 auto sliceableModel =
109 ModelById::getAs<DenseThreeDimensionalModel>(m_sliceableModel);
110 if (!sliceableModel) return "";
123 111
124 if (m_binAlignment == BinsSpanScalePoints) { 112 if (m_binAlignment == BinsSpanScalePoints) {
125 minbin = int(getBinForX(v, p.x())); 113 minbin = int(getBinForX(v, p.x()));
126 maxbin = int(getBinForX(v, p.x() + 1)); 114 maxbin = int(getBinForX(v, p.x() + 1));
127 } else { 115 } else {
128 minbin = int(getBinForX(v, p.x()) + 0.5); 116 minbin = int(getBinForX(v, p.x()) + 0.5);
129 maxbin = int(getBinForX(v, p.x() + 1) + 0.5); 117 maxbin = int(getBinForX(v, p.x() + 1) + 0.5);
130 } 118 }
131 119
132 int mh = m_sliceableModel->getHeight(); 120 int mh = sliceableModel->getHeight();
133 if (minbin >= mh) minbin = mh - 1; 121 if (minbin >= mh) minbin = mh - 1;
134 if (maxbin >= mh) maxbin = mh - 1; 122 if (maxbin >= mh) maxbin = mh - 1;
135 if (minbin < 0) minbin = 0; 123 if (minbin < 0) minbin = 0;
136 if (maxbin < 0) maxbin = 0; 124 if (maxbin < 0) maxbin = 0;
137 125
138 sv_samplerate_t sampleRate = m_sliceableModel->getSampleRate(); 126 sv_samplerate_t sampleRate = sliceableModel->getSampleRate();
139 127
140 sv_frame_t f0 = m_currentf0; 128 sv_frame_t f0 = m_currentf0;
141 sv_frame_t f1 = m_currentf1; 129 sv_frame_t f1 = m_currentf1;
142 130
143 RealTime rt0 = RealTime::frame2RealTime(f0, sampleRate); 131 RealTime rt0 = RealTime::frame2RealTime(f0, sampleRate);
418 } 406 }
419 407
420 void 408 void
421 SliceLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const 409 SliceLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const
422 { 410 {
423 if (!m_sliceableModel || 411 auto sliceableModel =
424 !m_sliceableModel->isOK() || 412 ModelById::getAs<DenseThreeDimensionalModel>(m_sliceableModel);
425 !m_sliceableModel->isReady()) return; 413 if (!sliceableModel ||
414 !sliceableModel->isOK() ||
415 !sliceableModel->isReady()) return;
426 416
427 Profiler profiler("SliceLayer::paint()"); 417 Profiler profiler("SliceLayer::paint()");
428 418
429 paint.save(); 419 paint.save();
430 paint.setRenderHint(QPainter::Antialiasing, true); 420 paint.setRenderHint(QPainter::Antialiasing, true);
440 rect.width(), m_scalePoints[i] * ratio); 430 rect.width(), m_scalePoints[i] * ratio);
441 } 431 }
442 } 432 }
443 } 433 }
444 434
445 int mh = m_sliceableModel->getHeight(); 435 int mh = sliceableModel->getHeight();
446 int bin0 = 0; 436 int bin0 = 0;
447 if (m_maxbin > m_minbin) { 437 if (m_maxbin > m_minbin) {
448 mh = m_maxbin - m_minbin; 438 mh = m_maxbin - m_minbin;
449 bin0 = m_minbin; 439 bin0 = m_minbin;
450 } 440 }
491 sv_frame_t f1 = v->getFrameForX(f0x + 1); 481 sv_frame_t f1 = v->getFrameForX(f0x + 1);
492 if (f1 > f0) --f1; 482 if (f1 > f0) --f1;
493 483
494 // cerr << "centre frame " << v->getCentreFrame() << ", x " << f0x << ", f0 " << f0 << ", f1 " << f1 << endl; 484 // cerr << "centre frame " << v->getCentreFrame() << ", x " << f0x << ", f0 " << f0 << ", f1 " << f1 << endl;
495 485
496 int res = m_sliceableModel->getResolution(); 486 int res = sliceableModel->getResolution();
497 int col0 = int(f0 / res); 487 int col0 = int(f0 / res);
498 int col1 = col0; 488 int col1 = col0;
499 if (m_samplingMode != NearestSample) col1 = int(f1 / res); 489 if (m_samplingMode != NearestSample) col1 = int(f1 / res);
500 f0 = col0 * res; 490 f0 = col0 * res;
501 f1 = (col1 + 1) * res - 1; 491 f1 = (col1 + 1) * res - 1;
510 getBiasCurve(curve); 500 getBiasCurve(curve);
511 int cs = int(curve.size()); 501 int cs = int(curve.size());
512 502
513 for (int col = col0; col <= col1; ++col) { 503 for (int col = col0; col <= col1; ++col) {
514 DenseThreeDimensionalModel::Column column = 504 DenseThreeDimensionalModel::Column column =
515 m_sliceableModel->getColumn(col); 505 sliceableModel->getColumn(col);
516 for (int bin = 0; bin < mh; ++bin) { 506 for (int bin = 0; bin < mh; ++bin) {
517 float value = column[bin0 + bin]; 507 float value = column[bin0 + bin];
518 if (bin < cs) value *= curve[bin]; 508 if (bin < cs) value *= curve[bin];
519 if (m_samplingMode == SamplePeak) { 509 if (m_samplingMode == SamplePeak) {
520 if (value > m_values[bin]) m_values[bin] = value; 510 if (value > m_values[bin]) m_values[bin] = value;
672 } 662 }
673 663
674 int 664 int
675 SliceLayer::getVerticalScaleWidth(LayerGeometryProvider *, bool, QPainter &paint) const 665 SliceLayer::getVerticalScaleWidth(LayerGeometryProvider *, bool, QPainter &paint) const
676 { 666 {
667 // Qt 5.13 deprecates QFontMetrics::width(), but its suggested
668 // replacement (horizontalAdvance) was only added in Qt 5.11
669 // which is too new for us
670 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
671
677 int width; 672 int width;
678 if (m_energyScale == LinearScale || m_energyScale == AbsoluteScale) { 673 if (m_energyScale == LinearScale || m_energyScale == AbsoluteScale) {
679 width = std::max(paint.fontMetrics().width("0.0") + 13, 674 width = std::max(paint.fontMetrics().width("0.0") + 13,
680 paint.fontMetrics().width("x10-10")); 675 paint.fontMetrics().width("x10-10"));
681 } else { 676 } else {
1164 1159
1165 bool 1160 bool
1166 SliceLayer::getValueExtents(double &min, double &max, bool &logarithmic, 1161 SliceLayer::getValueExtents(double &min, double &max, bool &logarithmic,
1167 QString &unit) const 1162 QString &unit) const
1168 { 1163 {
1169 if (!m_sliceableModel) return false; 1164 auto sliceableModel =
1165 ModelById::getAs<DenseThreeDimensionalModel>(m_sliceableModel);
1166 if (!sliceableModel) return false;
1170 1167
1171 min = 0; 1168 min = 0;
1172 max = double(m_sliceableModel->getHeight()); 1169 max = double(sliceableModel->getHeight());
1173 1170
1174 logarithmic = (m_binScale == BinScale::LogBins); 1171 logarithmic = (m_binScale == BinScale::LogBins);
1175 unit = ""; 1172 unit = "";
1176 1173
1177 return true; 1174 return true;
1178 } 1175 }
1179 1176
1180 bool 1177 bool
1181 SliceLayer::getDisplayExtents(double &min, double &max) const 1178 SliceLayer::getDisplayExtents(double &min, double &max) const
1182 { 1179 {
1183 if (!m_sliceableModel) return false; 1180 auto sliceableModel =
1184 1181 ModelById::getAs<DenseThreeDimensionalModel>(m_sliceableModel);
1185 double hmax = double(m_sliceableModel->getHeight()); 1182 if (!sliceableModel) return false;
1183
1184 double hmax = double(sliceableModel->getHeight());
1186 1185
1187 min = m_minbin; 1186 min = m_minbin;
1188 max = m_maxbin; 1187 max = m_maxbin;
1189 if (max <= min) { 1188 if (max <= min) {
1190 min = 0; 1189 min = 0;
1197 } 1196 }
1198 1197
1199 bool 1198 bool
1200 SliceLayer::setDisplayExtents(double min, double max) 1199 SliceLayer::setDisplayExtents(double min, double max)
1201 { 1200 {
1202 if (!m_sliceableModel) return false; 1201 auto sliceableModel =
1202 ModelById::getAs<DenseThreeDimensionalModel>(m_sliceableModel);
1203 if (!sliceableModel) return false;
1203 1204
1204 m_minbin = int(lrint(min)); 1205 m_minbin = int(lrint(min));
1205 m_maxbin = int(lrint(max)); 1206 m_maxbin = int(lrint(max));
1206 1207
1207 if (m_minbin < 0) { 1208 if (m_minbin < 0) {
1208 m_minbin = 0; 1209 m_minbin = 0;
1209 } 1210 }
1210 if (m_maxbin < 0) { 1211 if (m_maxbin < 0) {
1211 m_maxbin = 0; 1212 m_maxbin = 0;
1212 } 1213 }
1213 if (m_minbin > m_sliceableModel->getHeight()) { 1214 if (m_minbin > sliceableModel->getHeight()) {
1214 m_minbin = m_sliceableModel->getHeight(); 1215 m_minbin = sliceableModel->getHeight();
1215 } 1216 }
1216 if (m_maxbin > m_sliceableModel->getHeight()) { 1217 if (m_maxbin > sliceableModel->getHeight()) {
1217 m_maxbin = m_sliceableModel->getHeight(); 1218 m_maxbin = sliceableModel->getHeight();
1218 } 1219 }
1219 if (m_maxbin < m_minbin) { 1220 if (m_maxbin < m_minbin) {
1220 m_maxbin = m_minbin; 1221 m_maxbin = m_minbin;
1221 } 1222 }
1222 1223
1225 } 1226 }
1226 1227
1227 int 1228 int
1228 SliceLayer::getVerticalZoomSteps(int &defaultStep) const 1229 SliceLayer::getVerticalZoomSteps(int &defaultStep) const
1229 { 1230 {
1230 if (!m_sliceableModel) return 0; 1231 auto sliceableModel =
1232 ModelById::getAs<DenseThreeDimensionalModel>(m_sliceableModel);
1233 if (!sliceableModel) return 0;
1231 1234
1232 defaultStep = 0; 1235 defaultStep = 0;
1233 int h = m_sliceableModel->getHeight(); 1236 int h = sliceableModel->getHeight();
1234 return h; 1237 return h;
1235 } 1238 }
1236 1239
1237 int 1240 int
1238 SliceLayer::getCurrentVerticalZoomStep() const 1241 SliceLayer::getCurrentVerticalZoomStep() const
1239 { 1242 {
1240 if (!m_sliceableModel) return 0; 1243 auto sliceableModel =
1244 ModelById::getAs<DenseThreeDimensionalModel>(m_sliceableModel);
1245 if (!sliceableModel) return 0;
1241 1246
1242 double min, max; 1247 double min, max;
1243 getDisplayExtents(min, max); 1248 getDisplayExtents(min, max);
1244 return m_sliceableModel->getHeight() - int(lrint(max - min)); 1249 return sliceableModel->getHeight() - int(lrint(max - min));
1245 } 1250 }
1246 1251
1247 void 1252 void
1248 SliceLayer::setVerticalZoomStep(int step) 1253 SliceLayer::setVerticalZoomStep(int step)
1249 { 1254 {
1250 if (!m_sliceableModel) return; 1255 auto sliceableModel =
1256 ModelById::getAs<DenseThreeDimensionalModel>(m_sliceableModel);
1257 if (!sliceableModel) return;
1251 1258
1252 // SVDEBUG << "SliceLayer::setVerticalZoomStep(" <<step <<"): before: minbin = " << m_minbin << ", maxbin = " << m_maxbin << endl; 1259 // SVDEBUG << "SliceLayer::setVerticalZoomStep(" <<step <<"): before: minbin = " << m_minbin << ", maxbin = " << m_maxbin << endl;
1253 1260
1254 int dist = m_sliceableModel->getHeight() - step; 1261 int dist = sliceableModel->getHeight() - step;
1255 if (dist < 1) dist = 1; 1262 if (dist < 1) dist = 1;
1256 double centre = m_minbin + (m_maxbin - m_minbin) / 2.0; 1263 double centre = m_minbin + (m_maxbin - m_minbin) / 2.0;
1257 int minbin = int(lrint(centre - dist/2.0)); 1264 int minbin = int(lrint(centre - dist/2.0));
1258 int maxbin = minbin + dist; 1265 int maxbin = minbin + dist;
1259 setDisplayExtents(minbin, maxbin); 1266 setDisplayExtents(minbin, maxbin);
1260 } 1267 }
1261 1268
1262 RangeMapper * 1269 RangeMapper *
1263 SliceLayer::getNewVerticalZoomRangeMapper() const 1270 SliceLayer::getNewVerticalZoomRangeMapper() const
1264 { 1271 {
1265 if (!m_sliceableModel) return nullptr; 1272 auto sliceableModel =
1266 1273 ModelById::getAs<DenseThreeDimensionalModel>(m_sliceableModel);
1267 return new LinearRangeMapper(0, m_sliceableModel->getHeight(), 1274 if (!sliceableModel) return nullptr;
1268 0, m_sliceableModel->getHeight(), ""); 1275
1276 return new LinearRangeMapper(0, sliceableModel->getHeight(),
1277 0, sliceableModel->getHeight(), "");
1269 } 1278 }
1270 1279
1271 void 1280 void
1272 SliceLayer::zoomToRegion(const LayerGeometryProvider *v, QRect rect) 1281 SliceLayer::zoomToRegion(const LayerGeometryProvider *v, QRect rect)
1273 { 1282 {