libpappsomspp
Library for mass spectrometry
Loading...
Searching...
No Matches
basecolormapplotwidget.cpp
Go to the documentation of this file.
1/* This code comes right from the msXpertSuite software project.
2 *
3 * msXpertSuite - mass spectrometry software suite
4 * -----------------------------------------------
5 * Copyright(C) 2009,...,2018 Filippo Rusconi
6 *
7 * http://www.msxpertsuite.org
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 *
22 * END software license
23 */
24
25
26/////////////////////// StdLib includes
27#include <vector>
28
29
30/////////////////////// Qt includes
31#include <QVector>
32
33
34/////////////////////// Local includes
38
39
40namespace pappso
41{
42
43
45 const QString &x_axis_label,
46 const QString &y_axis_label)
47 : BasePlotWidget(parent, x_axis_label, y_axis_label)
48{
49 // Do not call createAllAncillaryItems() in this base class because all the
50 // items will have been created *before* the addition of plots and then the
51 // rendering order will hide them to the viewer, since the rendering order is
52 // according to the order in which the items have been created.
53 //
54 // The fact that the ancillary items are created before trace plots is not a
55 // problem because the trace plots are sparse and do not effectively hide the
56 // data.
57 //
58 // But, in the color map plot widgets, we cannot afford to create the
59 // ancillary items *before* the plot itself because then, the rendering of the
60 // plot (created after) would screen off the ancillary items (created before).
61 //
62 // So, the createAllAncillaryItems() function needs to be called in the
63 // derived classes at the most appropriate moment in the setting up of the
64 // widget.
65 //
66 // In the present case, the function needs to be called right after addition
67 // of the color map plot.
68}
69
70
72 : BasePlotWidget(parent, "x", "y")
73{
74 // Do not call createAllAncillaryItems() in this base class because all the
75 // items will have been created *before* the addition of plots and then the
76 // rendering order will hide them to the viewer, since the rendering order is
77 // according to the order in which the items have been created.
78 //
79 // The fact that the ancillary items are created before trace plots is not a
80 // problem because the trace plots are sparse and do not effectively hide the
81 // data.
82 //
83 // But, in the color map plot widgets, we cannot afford to create the
84 // ancillary items *before* the plot itself because then, the rendering of the
85 // plot (created after) would screen off the ancillary items (created before).
86 //
87 // So, the createAllAncillaryItems() function needs to be called in the
88 // derived classes at the most appropriate moment in the setting up of the
89 // widget.
90 //
91 // In the present case, the function needs to be called right after addition
92 // of the color map plot.
93}
94
95
96//! Destruct \c this BaseColorMapPlotWidget instance.
97/*!
98
99 The destruction involves clearing the history, deleting all the axis range
100 history items for x and y axes.
101
102*/
111
112
113void
115 const ColorMapPlotConfig &color_map_config)
116{
117 m_colorMapPlotConfig = color_map_config;
118}
119
120
121const ColorMapPlotConfig *
126
127
128const ColorMapPlotConfig &
133
134
135QCPColorMap *
137 std::shared_ptr<std::map<double, MapTrace>> double_map_trace_map_sp,
138 const ColorMapPlotConfig color_map_plot_config,
139 const QColor &color)
140{
141 // qDebug() << "Adding color map with config:" <<
142 // color_map_plot_config.toString();
143
144 if(!color.isValid())
145 throw PappsoException(
146 QString("The color to be used for the plot graph is invalid."));
147
148 QCPColorMap *color_map_p = new QCPColorMap(xAxis, yAxis);
149
150 color_map_p->setLayer("plotsLayer");
151
152 // Do not forget to copy the config!
153 m_colorMapPlotConfig = color_map_plot_config;
154
155 // Immediately create a copy of the original data for backup.
156 mpa_origColorMapPlotConfig = new ColorMapPlotConfig(color_map_plot_config);
157
158#if 0
159 // This is the code on the QCustomPlot documentation and it works fine.
160 QCPColorMap *color_map_p = new QCPColorMap(xAxis, yAxis);
161
162 color_map_p->data()->setSize(50, 50);
163 color_map_p->data()->setRange(QCPRange(0, 2), QCPRange(0, 2));
164 for(int x = 0; x < 50; ++x)
165 for(int y = 0; y < 50; ++y)
166 color_map_p->data()->setCell(x, y, qCos(x / 10.0) + qSin(y / 10.0));
167 color_map_p->setGradient(QCPColorGradient::gpPolar);
168 color_map_p->rescaleDataRange(true);
169 rescaleAxes();
170 replot();
171#endif
172
173 // Only now can afford to call createAllAncillaryItems() in this derived class
174 // because the color map has been created already. The rendering order will
175 // thus not hide the ancillary items, since they have been created after the
176 // color map plot (since the rendering order is according to the
177 // order in which the items have been created). See contructor note.
179
180 // Connect the signal of selection change so that we can re-emit it for the
181 // widget that is using *this widget.
182
183 connect(color_map_p,
184 static_cast<void (QCPAbstractPlottable::*)(bool)>(
185 &QCPAbstractPlottable::selectionChanged),
186 [this, color_map_p]() {
187 emit plottableSelectionChangedSignal(color_map_p,
188 color_map_p->selected());
189 });
190
191 // qDebug() << "Configuring the color map with this config:"
192 //<< color_map_plot_config.toString();
193
194 color_map_p->data()->setSize(color_map_plot_config.keyCellCount,
195 color_map_plot_config.mzCellCount);
196
197 color_map_p->data()->setRange(QCPRange(color_map_plot_config.minKeyValue,
198 color_map_plot_config.maxKeyValue),
199 QCPRange(color_map_plot_config.minMzValue,
200 color_map_plot_config.maxMzValue));
201 color_map_p->data()->fill(0.0);
202
203 // We have now to fill the color map.
204
205 for(auto &&pair : *double_map_trace_map_sp)
206 {
207
208 // The first value is the key and the second value is the MapTrace into
209 // which we need to iterated and for each point (double mz, double
210 // intensity) create a map cell.
211
212 double dt_or_rt_key = pair.first;
213 MapTrace map_trace = pair.second;
214
215 for(auto &&data_point_pair : map_trace)
216 {
217 double mz = data_point_pair.first;
218 double intensity = data_point_pair.second;
219
220 // We are filling dynamically the color map. If a cell had already
221 // something in, then we need to take that into account. This is
222 // because we let QCustomPlot handle the fuzzy transition between
223 // color map plot cells.
224
225 double prev_intensity = color_map_p->data()->data(dt_or_rt_key, mz);
226 double new_intensity = prev_intensity + intensity;
227
228 // Record the min/max cell intensity value (origM(in/ax)ZValue). We
229 // will need that later. Also update the lastM(in/ax)ZValue because
230 // when doing this kind of data conversion it is assume that the user
231 // actually changes the data.
233 std::min(m_colorMapPlotConfig.origMinZValue, new_intensity));
234
236 std::max(m_colorMapPlotConfig.origMaxZValue, new_intensity));
237
238 // qDebug() << "Setting tri-point:" << dt_or_rt_key << "," << mz <<
239 // ","
240 //<< new_intensity;
241
242 color_map_p->data()->setData(dt_or_rt_key, mz, new_intensity);
243 }
244 }
245
246 // At this point we have finished filling-up the color map.
247
248 // The gpThermal is certainly one of the best.
249
250 color_map_p->setGradient(QCPColorGradient::gpThermal);
251
252 color_map_p->rescaleDataRange(true);
253
254 color_map_p->rescaleAxes();
256
257 // The pen of the color map itself is of no use. Instead the user will see the
258 // color of the axes' labels.
259
260 QPen pen = xAxis->basePen();
261 pen.setColor(color);
262
263 xAxis->setBasePen(pen);
264 xAxis->setLabelColor(color);
265 xAxis->setTickLabelColor(color);
266
267 yAxis->setBasePen(pen);
268 yAxis->setLabelColor(color);
269 yAxis->setTickLabelColor(color);
270
271 // And now set the color map's pen to the same color, even if we do not use
272 // it, we need it for coloring the plots that might be integrated from this
273 // color map.
274
275 color_map_p->setPen(pen);
276
277 // Copy the original color map's data into a backup copy.
278
279 mpa_origColorMapData = new QCPColorMapData(*(color_map_p->data()));
280
281 replot();
282
283 return color_map_p;
284}
285
286QCPColorMap *
288 const TimsFrame &tims_frame,
289 const ColorMapPlotConfig color_map_plot_config,
290 const QColor &color)
291{
292 qDebug();
293 if(!color.isValid())
294 throw PappsoException(
295 QString("The color to be used for the plot graph is invalid."));
296
297 QCPColorMap *color_map_p = new QCPColorMap(xAxis, yAxis);
298
299 color_map_p->setLayer("plotsLayer");
300
301 // Do not forget to copy the config!
302 m_colorMapPlotConfig = color_map_plot_config;
303
304 // Immediately create a copy of the original data for backup.
305 mpa_origColorMapPlotConfig = new ColorMapPlotConfig(color_map_plot_config);
306
307 qDebug();
308#if 0
309 // This is the code on the QCustomPlot documentation and it works fine.
310 QCPColorMap *color_map_p = new QCPColorMap(xAxis, yAxis);
311
312 color_map_p->data()->setSize(50, 50);
313 color_map_p->data()->setRange(QCPRange(0, 2), QCPRange(0, 2));
314 for(int x = 0; x < 50; ++x)
315 for(int y = 0; y < 50; ++y)
316 color_map_p->data()->setCell(x, y, qCos(x / 10.0) + qSin(y / 10.0));
317 color_map_p->setGradient(QCPColorGradient::gpPolar);
318 color_map_p->rescaleDataRange(true);
319 rescaleAxes();
320 replot();
321#endif
322
323 // Only now can afford to call createAllAncillaryItems() in this derived class
324 // because the color map has been created already. The rendering order will
325 // thus not hide the ancillary items, since they have been created after the
326 // color map plot (since the rendering order is according to the
327 // order in which the items have been created). See contructor note.
329
330 qDebug();
331 // Connect the signal of selection change so that we can re-emit it for the
332 // widget that is using *this widget.
333
334 connect(color_map_p,
335 static_cast<void (QCPAbstractPlottable::*)(bool)>(
336 &QCPAbstractPlottable::selectionChanged),
337 [this, color_map_p]() {
338 emit plottableSelectionChangedSignal(color_map_p,
339 color_map_p->selected());
340 });
341
342 // qDebug() << "Configuring the color map with this config:"
343 //<< color_map_plot_config.toString();
344
345 color_map_p->data()->setSize(color_map_plot_config.keyCellCount,
346 color_map_plot_config.mzCellCount);
347
348 color_map_p->data()->setRange(QCPRange(color_map_plot_config.minKeyValue,
349 color_map_plot_config.maxKeyValue),
350 QCPRange(color_map_plot_config.minMzValue,
351 color_map_plot_config.maxMzValue));
352 color_map_p->data()->fill(0.0);
353 // double max_intensity = 0;
354 qDebug();
355 // We have now to fill the color map.
356 std::size_t number_of_scans = tims_frame.getTotalNumberOfScans();
357 for(std::size_t i = 0; i < number_of_scans; i++)
358 {
359 std::vector<quint32> tof_index_vector = tims_frame.getScanTofIndexList(i);
360 std::vector<quint32> intensity_index_vector =
361 tims_frame.getScanIntensityList(i);
362
363
364 // The first value is the key and the second value is the MapTrace into
365 // which we need to iterated and for each point (double mz, double
366 // intensity) create a map cell.
367
368 double dt_or_rt_key = i;
369 std::size_t vector_index = 0;
370 for(quint32 mzindex : tof_index_vector)
371 {
372 double mz = mzindex;
373 double intensity = intensity_index_vector.at(vector_index);
374 // max_intensity = std::max(max_intensity, intensity);
375 // We are filling dynamically the color map. If a cell had already
376 // something in, then we need to take that into account. This is
377 // because we let QCustomPlot handle the fuzzy transition between
378 // color map plot cells.
379
380 double prev_intensity = color_map_p->data()->data(dt_or_rt_key, mz);
381 double new_intensity = prev_intensity + intensity;
382
383 // qDebug() << "mz=" << mz << " int=" << intensity;
384
385 // Record the min/max cell intensity value (origM(in/ax)ZValue). We
386 // will need that later. Also update the lastM(in/ax)ZValue because
387 // when doing this kind of data conversion it is assume that the user
388 // actually changes the data.
390 std::min(m_colorMapPlotConfig.origMinZValue, new_intensity));
391
393 std::max(m_colorMapPlotConfig.origMaxZValue, new_intensity));
394
395 // qDebug() << "Setting tri-point:" << dt_or_rt_key << "," << mz <<
396 // ","
397 //<< new_intensity;
398
399 color_map_p->data()->setCell(dt_or_rt_key, mz, new_intensity);
400
401 // qDebug() << "dt_or_rt_key=" << dt_or_rt_key << " mz=" << mz
402 // << " new_intensity=" << new_intensity;
403
404 vector_index++;
405 }
406 }
407
408 // At this point we have finished filling-up the color map.
409
410 // The gpThermal is certainly one of the best.
411
412 color_map_p->setGradient(QCPColorGradient::gpThermal);
413
414 color_map_p->data()->recalculateDataBounds();
415 color_map_p->rescaleDataRange(true);
416
417 color_map_p->rescaleAxes();
419
420 // The pen of the color map itself is of no use. Instead the user will see the
421 // color of the axes' labels.
422
423 qDebug();
424 QPen pen = xAxis->basePen();
425 pen.setColor(color);
426
427 xAxis->setBasePen(pen);
428 xAxis->setLabelColor(color);
429 xAxis->setTickLabelColor(color);
430
431 yAxis->setBasePen(pen);
432 yAxis->setLabelColor(color);
433 yAxis->setTickLabelColor(color);
434
435 // And now set the color map's pen to the same color, even if we do not use
436 // it, we need it for coloring the plots that might be integrated from this
437 // color map.
438
439 color_map_p->setPen(pen);
440
441 // Copy the original color map's data into a backup copy.
442
443 mpa_origColorMapData = new QCPColorMapData(*(color_map_p->data()));
444
445 color_map_p->setInterpolate(false);
446 color_map_p->setTightBoundary(false);
447
448 replot();
449
450
451 qDebug() << color_map_p->data()->keyRange();
452 qDebug() << color_map_p->data()->valueRange();
453 qDebug() << color_map_p->data()->dataBounds();
454 qDebug();
455 return color_map_p;
456}
457
458void
460{
461 // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()" ;
462
463 QCPColorMap *color_map_p = static_cast<QCPColorMap *>(plottable(0));
464
465 QCPColorMapData *origData = color_map_p->data();
466
467 int keySize = origData->keySize();
468 int valueSize = origData->valueSize();
469
470 // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()"
471 //<< "Orig data size:" << keySize << valueSize;
472
473 QCPRange keyRange = origData->keyRange();
474 QCPRange valueRange = origData->valueRange();
475
476 // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()"
477 //<< "Value at cell 80,650:" << origData->cell(80,650);
478
479 // Transposed map.
480 QCPColorMapData *newData =
481 new QCPColorMapData(valueSize, keySize, valueRange, keyRange);
482
483 for(int iter = 0; iter < keySize; ++iter)
484 {
485 for(int jter = 0; jter < valueSize; ++jter)
486 {
487 double cellData = origData->cell(iter, jter);
488
489 newData->setCell(jter, iter, cellData);
490 }
491 }
492
493 // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()"
494 //<< "New data size:" << newData->keySize() << newData->valueSize();
495
496 // At this point the transposition has been done.
497
498 color_map_p->data()->clear();
499 color_map_p->rescaleDataRange(true);
500
501 // Now we need to invert the labels and data kinds.
502
505 m_colorMapPlotConfig.yAxisDataKind = temp_data_kind;
506
507 QString temp_axis_label = xAxis->label();
508 xAxis->setLabel(yAxis->label());
509 yAxis->setLabel(temp_axis_label);
510
511 // Will take ownership of the newData.
512 color_map_p->setData(newData);
513
514 // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()"
515 //<< "Value at cell 80,650:" << newData->cell(80,650)
516 //<< "Value at cell 650, 80:" << newData->cell(650,80);
517
518 // QCPAxis *p_keyAxis = mp_colorMap->keyAxis();
519 // QCPAxis *p_valueAxis = mp_colorMap->valueAxis();
520
521 // mp_colorMap->setKeyAxis(p_valueAxis);
522 // mp_colorMap->setValueAxis(p_keyAxis);
523
524 color_map_p->rescaleAxes();
525
526 replot();
527}
528
529
530void
532{
533 // The user wants to rescale the intensity values of the color map according
534 // to: new_int = log10(orig_int).
535
536 // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()" ;
537
539 {
540 qDebug() << "Asking to change z axis scale to log10 while it is already "
541 "like so.";
542
543 return;
544 }
545
546 // qDebug() << "m_colorMapPlotConfig:" << m_colorMapPlotConfig.toString();
547
548 QCPColorMap *color_map_p = static_cast<QCPColorMap *>(plottable(0));
549
550 QCPColorMapData *map_data = color_map_p->data();
551
552 int keySize = map_data->keySize();
553 int valueSize = map_data->valueSize();
554
555 QCPRange keyRange = map_data->keyRange();
556 QCPRange valueRange = map_data->valueRange();
557
558 // Make a copy of the current config so that we can modify
559 // the xxxZvalue values.
560 ColorMapPlotConfig new_color_map_plot_config(m_colorMapPlotConfig);
561
562 // But we need to reset these two values to be able to update them using
563 // std::min() and std::max() below.
564 new_color_map_plot_config.setOrigAndLastMinZValue(
565 std::numeric_limits<double>::max());
566
567 new_color_map_plot_config.setOrigAndLastMaxZValue(
568 std::numeric_limits<double>::min());
569
570 // qDebug() << "new_color_map_plot_config"
571 //<< new_color_map_plot_config.toString();
572
573 // Log-ified heat map.
574 QCPColorMapData *new_map_data =
575 new QCPColorMapData(keySize, valueSize, keyRange, valueRange);
576
577 // qDebug() << "Starting iteration in the color map.";
578
579 for(int iter = 0; iter < keySize; ++iter)
580 {
581 for(int jter = 0; jter < valueSize; ++jter)
582 {
583 double cell_data = map_data->cell(iter, jter);
584
585 double new_cell_data = 0;
586
587 if(!cell_data)
588 // The log10 would be -inf, but then we'd have a huge data range and
589 // the color map would look totally blue... that is like 0 intensity
590 // all over.
591 new_cell_data = -1;
592 else
593 new_cell_data = std::log10(cell_data);
594
595 // Store the new values here. Should we change the last or orig or
596 // both ?
597 new_color_map_plot_config.lastMinZValue =
598 //(new_cell_data < new_color_map_plot_config.minZValue
599 //? new_cell_data
600 //: new_color_map_plot_config.minZValue);
601 std::min(new_color_map_plot_config.lastMinZValue, new_cell_data);
602
603 new_color_map_plot_config.lastMaxZValue =
604 //(new_cell_data > new_color_map_plot_config.maxZValue
605 //? new_cell_data
606 //: new_color_map_plot_config.maxZValue);
607 std::max(new_color_map_plot_config.lastMaxZValue, new_cell_data);
608
609 // qDebug() << "cell_data:" << cell_data
610 //<< "new_cell_data:" << new_cell_data
611 //<< "new_color_map_plot_config.minZValue:"
612 //<< new_color_map_plot_config.minZValue
613 //<< "new_color_map_plot_config.maxZValue:"
614 //<< new_color_map_plot_config.maxZValue;
615
616 new_map_data->setCell(iter, jter, new_cell_data);
617 }
618 }
619
620 // qDebug() << "Finished iteration in the color map.";
621
622 color_map_p->data()->clear();
623
624 // Will take ownership of the new_map_data.
625 color_map_p->setData(new_map_data);
626
627 color_map_p->data()->recalculateDataBounds();
628 color_map_p->rescaleDataRange(true);
629
630 // At this point the new color map data have taken their place, we can update
631 // the config. This, way any new filtering can take advantage of the new
632 // values and compute the threshold correctly.
633 m_colorMapPlotConfig = new_color_map_plot_config;
634
635 // Now we need to document the change.
637
638 // qDebug() << "new_color_map_plot_config"
639 //<< new_color_map_plot_config.toString();
640
641 // qDebug() << "m_colorMapPlotConfig:" << m_colorMapPlotConfig.toString();
642
643 // We should not do this, as the user might have zoomed to a region of
644 // interest.
645 // color_map_p->rescaleAxes();
646
647 replot();
648}
649
650void
652 double threshold_percentage)
653{
654 // This filter allows all the values smaller than a threshold to remain
655 // unchanged. Instead, all the values above the threshold will be reset to
656 // that threshold.
657 //
658 // The effect of this filter is to enhance the high-intensity signal.
659
660 QCPColorMap *color_map_p = static_cast<QCPColorMap *>(plottable(0));
661
662 QCPColorMapData *map_data = color_map_p->data();
663
664 int keySize = map_data->keySize();
665 int valueSize = map_data->valueSize();
666
667 QCPRange keyRange = map_data->keyRange();
668 QCPRange valueRange = map_data->valueRange();
669
670 double minZValue = m_colorMapPlotConfig.lastMinZValue;
671 double maxZValue = m_colorMapPlotConfig.lastMaxZValue;
672
673 double amplitude = maxZValue - minZValue;
674
675 double amplitude_fraction = amplitude * threshold_percentage / 100;
676
677 double threshold = minZValue + amplitude_fraction;
678
679 // qDebug() << "Before filtering minZValue:" << minZValue
680 //<< "maxZValue:" << maxZValue << "fraction:" << fraction
681 //<< "threshold:" << threshold
682 //<< "new threshold percentage:" << new_threshold_percentage;
683
684 // Make a copy of the current config so that we can modify
685 // the xxxZvalue values.
686 ColorMapPlotConfig new_color_map_plot_config(m_colorMapPlotConfig);
687
688 // But we need to reset these two values to be able to update them using
689 // std::min() and std::max() below.
690 new_color_map_plot_config.lastMinZValue = std::numeric_limits<double>::max();
691 new_color_map_plot_config.lastMaxZValue = std::numeric_limits<double>::min();
692
693 // Filtered
694 QCPColorMapData *new_map_data =
695 new QCPColorMapData(keySize, valueSize, keyRange, valueRange);
696
697 for(int iter = 0; iter < keySize; ++iter)
698 {
699 for(int jter = 0; jter < valueSize; ++jter)
700 {
701 double cell_data = map_data->cell(iter, jter);
702
703 double new_cell_data = 0;
704
705 if(cell_data < threshold)
706 // Keep the value, we are in low-pass
707 new_cell_data = cell_data;
708 else
709 new_cell_data = threshold;
710
711 // Store the new values here.
712 new_color_map_plot_config.lastMinZValue =
713 //(new_cell_data < new_color_map_plot_config.minZValue
714 //? new_cell_data
715 //: new_color_map_plot_config.minZValue);
716 std::min(new_color_map_plot_config.lastMinZValue, new_cell_data);
717
718 new_color_map_plot_config.lastMaxZValue =
719 //(new_cell_data > new_color_map_plot_config.maxZValue
720 //? new_cell_data
721 //: new_color_map_plot_config.maxZValue);
722 std::max(new_color_map_plot_config.lastMaxZValue, new_cell_data);
723
724 // qDebug() << "cell_data:" << cell_data
725 //<< "new_cell_data:" << new_cell_data
726 //<< "new_color_map_plot_config.minZValue:"
727 //<< new_color_map_plot_config.minZValue
728 //<< "new_color_map_plot_config.maxZValue:"
729 //<< new_color_map_plot_config.maxZValue;
730
731 new_map_data->setCell(iter, jter, new_cell_data);
732 }
733 }
734
735 color_map_p->data()->clear();
736
737 // Will take ownership of the new_map_data.
738 color_map_p->setData(new_map_data);
739
740 color_map_p->data()->recalculateDataBounds();
741 color_map_p->rescaleDataRange(true);
742
743
744 // At this point the new color map data have taken their place, we can update
745 // the config. This, way any new filtering can take advantage of the new
746 // values and compute the threshold correctly.
747 m_colorMapPlotConfig = new_color_map_plot_config;
748
749 // qDebug() << "Member colormap plot config is now, after filter was applied:"
750 //<< m_colorMapPlotConfig.toString();
751
752 // We should not do this, as the user might have zoomed to a region of
753 // interest.
754 // color_map_p->rescaleAxes();
755
756 replot();
757}
758
759
760void
762{
763
764 // This filter allows all the values smaller than a threshold to remain
765 // unchanged. Instead, all the values above the threshold will be reset to
766 // that threshold.
767
768 QCPColorMap *color_map_p = static_cast<QCPColorMap *>(plottable(0));
769
770 QCPColorMapData *map_data = color_map_p->data();
771
772 int keySize = map_data->keySize();
773 int valueSize = map_data->valueSize();
774
775 QCPRange keyRange = map_data->keyRange();
776 QCPRange valueRange = map_data->valueRange();
777
778 // qDebug() << "Before filtering minZValue:" << minZValue
779 //<< "maxZValue:" << maxZValue << "fraction:" << fraction
780 //<< "threshold:" << threshold
781 //<< "new threshold percentage:" << new_threshold_percentage;
782
783 // Make a copy of the current config so that we can modify
784 // the xxxZvalue values.
785 ColorMapPlotConfig new_color_map_plot_config(m_colorMapPlotConfig);
786
787 // But we need to reset these two values to be able to update them using
788 // std::min() and std::max() below.
789 new_color_map_plot_config.lastMinZValue = std::numeric_limits<double>::max();
790 new_color_map_plot_config.lastMaxZValue = std::numeric_limits<double>::min();
791
792 // Filtered
793 QCPColorMapData *new_map_data =
794 new QCPColorMapData(keySize, valueSize, keyRange, valueRange);
795
796 for(int iter = 0; iter < keySize; ++iter)
797 {
798 for(int jter = 0; jter < valueSize; ++jter)
799 {
800 double cell_data = map_data->cell(iter, jter);
801
802 double new_cell_data = 0;
803
804 if(cell_data < threshold)
805 // Keep the value, we are in low-pass
806 new_cell_data = cell_data;
807 else
808 new_cell_data = threshold;
809
810 // Store the new values here.
811 new_color_map_plot_config.lastMinZValue =
812 //(new_cell_data < new_color_map_plot_config.minZValue
813 //? new_cell_data
814 //: new_color_map_plot_config.minZValue);
815 std::min(new_color_map_plot_config.lastMinZValue, new_cell_data);
816
817 new_color_map_plot_config.lastMaxZValue =
818 //(new_cell_data > new_color_map_plot_config.maxZValue
819 //? new_cell_data
820 //: new_color_map_plot_config.maxZValue);
821 std::max(new_color_map_plot_config.lastMaxZValue, new_cell_data);
822
823 // qDebug() << "cell_data:" << cell_data
824 //<< "new_cell_data:" << new_cell_data
825 //<< "new_color_map_plot_config.minZValue:"
826 //<< new_color_map_plot_config.minZValue
827 //<< "new_color_map_plot_config.maxZValue:"
828 //<< new_color_map_plot_config.maxZValue;
829
830 new_map_data->setCell(iter, jter, new_cell_data);
831 }
832 }
833
834 color_map_p->data()->clear();
835
836 // Will take ownership of the new_map_data.
837 color_map_p->setData(new_map_data);
838
839 color_map_p->data()->recalculateDataBounds();
840 color_map_p->rescaleDataRange(true);
841
842
843 // At this point the new color map data have taken their place, we can update
844 // the config. This, way any new filtering can take advantage of the new
845 // values and compute the threshold correctly.
846 m_colorMapPlotConfig = new_color_map_plot_config;
847
848 // qDebug() << "Member colormap plot config is now, after filter was applied:"
849 //<< m_colorMapPlotConfig.toString();
850
851 // We should not do this, as the user might have zoomed to a region of
852 // interest.
853 // color_map_p->rescaleAxes();
854
855 replot();
856}
857
858void
860 double threshold_percentage)
861{
862 // This filter allows all the value greater than a threshold to remain
863 // unchanged. Instead, all the values below the threshold will be reset to
864 // that threshold value.
865 //
866 // The effect of this filter is to reduce the low-intensity signal: reduce
867 // noise.
868
869 QCPColorMap *color_map_p = static_cast<QCPColorMap *>(plottable(0));
870
871 QCPColorMapData *map_data = color_map_p->data();
872
873 int keySize = map_data->keySize();
874 int valueSize = map_data->valueSize();
875
876 QCPRange keyRange = map_data->keyRange();
877 QCPRange valueRange = map_data->valueRange();
878
879 double minZValue = m_colorMapPlotConfig.lastMinZValue;
880 double maxZValue = m_colorMapPlotConfig.lastMaxZValue;
881
882 double amplitude = maxZValue - minZValue;
883
884 double amplitude_fraction = amplitude * threshold_percentage / 100;
885
886 double threshold = minZValue + amplitude_fraction;
887
888 // qDebug() << "Before filtering minZValue:" << minZValue
889 //<< "maxZValue:" << maxZValue << "fraction:" << fraction
890 //<< "threshold:" << threshold
891 //<< "new threshold percentage:" << new_threshold_percentage;
892
893 // Make a copy of the current config so that we can modify
894 // the xxxZvalue values.
895 ColorMapPlotConfig new_color_map_plot_config(m_colorMapPlotConfig);
896
897 // But we need to reset these two values to be able to update them using
898 // std::min() and std::max() below.
899 new_color_map_plot_config.lastMinZValue = std::numeric_limits<double>::max();
900 new_color_map_plot_config.lastMaxZValue = std::numeric_limits<double>::min();
901
902 // Filtered
903 QCPColorMapData *new_map_data =
904 new QCPColorMapData(keySize, valueSize, keyRange, valueRange);
905
906 for(int iter = 0; iter < keySize; ++iter)
907 {
908 for(int jter = 0; jter < valueSize; ++jter)
909 {
910 double cell_data = map_data->cell(iter, jter);
911
912 double new_cell_data = 0;
913
914 if(cell_data > threshold)
915 // Keep the value, we are in high-pass
916 new_cell_data = cell_data;
917 else
918 new_cell_data = threshold;
919
920 // Store the new values here.
921 new_color_map_plot_config.lastMinZValue =
922 //(new_cell_data < new_color_map_plot_config.minZValue
923 //? new_cell_data
924 //: new_color_map_plot_config.minZValue);
925 std::min(new_color_map_plot_config.lastMinZValue, new_cell_data);
926
927 new_color_map_plot_config.lastMaxZValue =
928 //(new_cell_data > new_color_map_plot_config.maxZValue
929 //? new_cell_data
930 //: new_color_map_plot_config.maxZValue);
931 std::max(new_color_map_plot_config.lastMaxZValue, new_cell_data);
932
933 // qDebug() << "cell_data:" << cell_data
934 //<< "new_cell_data:" << new_cell_data
935 //<< "new_color_map_plot_config.minZValue:"
936 //<< new_color_map_plot_config.minZValue
937 //<< "new_color_map_plot_config.maxZValue:"
938 //<< new_color_map_plot_config.maxZValue;
939
940 new_map_data->setCell(iter, jter, new_cell_data);
941 }
942 }
943
944 color_map_p->data()->clear();
945
946 // Will take ownership of the new_map_data.
947 color_map_p->setData(new_map_data);
948
949 color_map_p->data()->recalculateDataBounds();
950 color_map_p->rescaleDataRange(true);
951
952
953 // At this point the new color map data have taken their place, we can update
954 // the config. This, way any new filtering can take advantage of the new
955 // values and compute the threshold correctly.
956 m_colorMapPlotConfig = new_color_map_plot_config;
957
958 // qDebug() << "Member colormap plot config is now, after filter was applied:"
959 //<< m_colorMapPlotConfig.toString();
960
961 // We should not do this, as the user might have zoomed to a region of
962 // interest.
963 // color_map_p->rescaleAxes();
964
965 replot();
966}
967
968
969void
971{
972 // The user might have changed to the axis scale to log10, for example.
973 // While doing this, the original data were still available in
974 // mpa_origColorMapData,with mpa_origColorMapPlotConfig. We need to reset the
975 // current data to the original data.
976 //
977 // Same thing for filters that might have been applied to the data.
978
979 QCPColorMap *color_map_p = static_cast<QCPColorMap *>(plottable(0));
980 color_map_p->data()->clear();
981
982 if(mpa_origColorMapData == nullptr)
983 throw(PappsoException(
984 "Not possible that the mpa_origColorMapData pointer be null."));
985
986 // We do no want that the color_map_p takes ownership of the data, because
987 // these must remain there always, so pass true, to say that we want to copy
988 // the data not transfer the pointer.
989 color_map_p->setData(mpa_origColorMapData, true);
990
991 color_map_p->data()->recalculateDataBounds();
992 color_map_p->rescaleDataRange(true);
993
994 // We should not do this, as the user might have zoomed to a region of
995 // interest.
996 // color_map_p->rescaleAxes();
997
998 // Reset the current plot config to what it was originally. The member
999 // m_colorMapPlotConfig.zAxisScale is now AxisScale::orig.
1001
1002 replot();
1003}
1004
1005
1011
1012
1018
1019
1022{
1023 if(axis == Axis::x)
1025 else if(axis == Axis::y)
1027 else if(axis == Axis::z)
1029 else
1030 throw PappsoException(
1031 QString("basecolormapplotwidget.cpp: The axis cannot be different than "
1032 "x, y or z."));
1033
1034 return AxisScale::unset;
1035}
1036
1037
1043
1044
1050
1051
1057
1058
1059void
1060BaseColorMapPlotWidget::setPlottingColor(QCPAbstractPlottable *plottable_p,
1061 const QColor &new_color)
1062{
1063 Q_UNUSED(plottable_p);
1064
1065 // The pen of the color map itself is of no use. Instead the user will see the
1066 // color of the axes' labels.
1067
1068 QPen pen = xAxis->basePen();
1069 pen.setColor(new_color);
1070
1071 xAxis->setBasePen(pen);
1072 xAxis->setLabelColor(new_color);
1073 xAxis->setTickLabelColor(new_color);
1074
1075 yAxis->setBasePen(pen);
1076 yAxis->setLabelColor(new_color);
1077 yAxis->setTickLabelColor(new_color);
1078
1079 // And now set the color map's pen to the same color, even if we do not use
1080 // it, we need it for coloring the plots that might be integrated from this
1081 // color map.
1082
1083 QCPColorMap *color_map_p = static_cast<QCPColorMap *>(plottable(0));
1084
1085 color_map_p->setPen(pen);
1086
1087 replot();
1088}
1089
1090
1091QColor
1093{
1094 Q_UNUSED(index);
1095
1096 QPen pen = xAxis->basePen();
1097 return pen.color();
1098}
1099
1100
1101void
1103{
1104 // We want to limit the ranges to the visible data range in the plot widget.
1105
1106 QCPColorMap *color_map_p = static_cast<QCPColorMap *>(plottable(0));
1107 QCPColorMapData *map_data = color_map_p->data();
1108
1109 bool found_range = false;
1110
1111 // Get the full data set DT values range because if the context contains no
1112 // values for the currently displayed ranges, then we fall back to them;
1113 QCPRange full_data_range = color_map_p->getKeyRange(found_range);
1114
1115 if(!found_range)
1116 {
1117 qDebug() << "The range was not found";
1118 return;
1119 }
1120
1121 // qDebug() << "Full key data range:" << full_data_range.lower << "-"
1122 //<< full_data_range.upper;
1123
1124 // But what we actually want is the currently visible axes ranges. And these
1125 // are stored in the context.
1126
1127 double visible_data_range_lower = m_context.m_xRange.lower;
1128 double visible_data_range_upper = m_context.m_xRange.upper;
1129
1130 // qDebug() << "Visible key data range:" << visible_data_range_lower << "-"
1131 //<< visible_data_range_upper;
1132
1133 // Note that if there has been *no* panning, rescale, nothing, with the color
1134 // map, then the context has no idea of the ranges. So we need to check that.
1135 // If that is the case, then we use the full key range as the full plot is
1136 // displayed full scale upon its first showing.
1137
1138 if(!visible_data_range_lower || !visible_data_range_upper)
1139 {
1140 visible_data_range_lower = full_data_range.lower;
1141 visible_data_range_upper = full_data_range.upper;
1142 }
1143
1144 // qDebug() << "Visible key range:" << visible_data_range_lower << "-"
1145 //<< visible_data_range_upper;
1146
1147 // And now convert the double value ranges into cell indices, which is what we
1148 // are being asked for.
1149
1150 map_data->coordToCell(visible_data_range_lower, 0, &lower, nullptr);
1151 map_data->coordToCell(visible_data_range_upper, 0, &upper, nullptr);
1152
1153 // qDebug() << "Cell indices for currently visible key range:" << lower << "-"
1154 //<< upper;
1155}
1156
1157
1158void
1160{
1161 // We want to limit the ranges to the visible data range in the plot widget.
1162
1163 QCPColorMap *color_map_p = static_cast<QCPColorMap *>(plottable(0));
1164 QCPColorMapData *map_data = color_map_p->data();
1165
1166 bool found_range = false;
1167
1168 // Get the full data set MZ values range because if the context contains no
1169 // values for the currently displayed ranges, then we fall back to them;
1170 QCPRange full_data_range = color_map_p->getValueRange(found_range);
1171
1172 if(!found_range)
1173 {
1174 qDebug() << "The range was not found";
1175 return;
1176 }
1177
1178 // qDebug() << "Full value data range:" << full_data_range.lower << "-"
1179 //<< full_data_range.upper;
1180
1181 // But what we actually want is the currently visible axes ranges. And these
1182 // are stored in the context.
1183
1184 double visible_data_range_lower = m_context.m_yRange.lower;
1185 double visible_data_range_upper = m_context.m_yRange.upper;
1186
1187 // qDebug() << "Visible value data range:" << visible_data_range_lower << "-"
1188 //<< visible_data_range_upper;
1189
1190 // Note that if there has been *no* panning, rescale, nothing, with the color
1191 // map, then the context has no idea of the ranges. So we need to check that.
1192 // If that is the case, then we use the full key range as the full plot is
1193 // displayed full scale upon its first showing.
1194
1195 if(!visible_data_range_lower || !visible_data_range_upper)
1196 {
1197 visible_data_range_lower = full_data_range.lower;
1198 visible_data_range_upper = full_data_range.upper;
1199 }
1200
1201 // qDebug() << "Final visible value data range:" << visible_data_range_lower
1202 //<< "-" << visible_data_range_upper;
1203
1204 // And now convert the double value ranges into cell indices, which is what we
1205 // are being asked for.
1206
1207 map_data->coordToCell(0, visible_data_range_lower, nullptr, &lower);
1208 map_data->coordToCell(0, visible_data_range_upper, nullptr, &upper);
1209
1210 // qDebug() << "Cell indices for currently visible value range:" << lower <<
1211 // "-"
1212 //<< upper;
1213}
1214
1215
1216void
1218{
1219 // We want to export the data to a string in the x y z format, with
1220 // x=key (cell's x coordinate)
1221 // y=value (cell's y coordinate)
1222 // z=intensity (cell value)
1223
1224 QCPColorMap *color_map_p = static_cast<QCPColorMap *>(plottable(0));
1225 QCPColorMapData *map_data = color_map_p->data();
1226
1227 int key_index_lower_range;
1228 int key_index_upper_range;
1229 currentXaxisRangeIndices(key_index_lower_range, key_index_upper_range);
1230
1231 // qDebug() << "Cell indices for currently visible key range:"
1232 //<< key_index_lower_range << "-" << key_index_upper_range;
1233
1234 int value_index_lower_range;
1235 int value_index_upper_range;
1236 currentYaxisRangeIndices(value_index_lower_range, value_index_upper_range);
1237
1238 // qDebug() << "Cell indices for currently visible value range:"
1239 //<< value_index_lower_range << "-" << value_index_upper_range;
1240
1241 data_string.clear();
1242 QString debug_string;
1243
1244 // Iterate in the matrix' key axis (DT, for example)
1245 for(int key_iter = key_index_lower_range; key_iter < key_index_upper_range;
1246 ++key_iter)
1247 {
1248 // Iterate in the matrix' value axis (MZ, for example)
1249 for(int value_iter = value_index_lower_range;
1250 value_iter < value_index_upper_range;
1251 ++value_iter)
1252 {
1253 // This would be the DT value (x axis)
1254 double key;
1255
1256 // This would be the MZ value (y axis)
1257 double value;
1258
1259 map_data->cellToCoord(key_iter, value_iter, &key, &value);
1260
1261 data_string +=
1262 QString("%1 %2 %3\n")
1263 .arg(key, 0, 'f', 6, ' ')
1264 .arg(value, 0, 'f', 6, ' ')
1265 // The intensity without decimals
1266 .arg(map_data->cell(key_iter, value_iter), 0, 'f', 0, ' ');
1267 }
1268 }
1269
1270 // qDebug() << "The completed data string has size: " << data_string.size();
1271}
1272
1273
1274void
1275BaseColorMapPlotWidget::dataToMatrixString(QString &data_string, bool detailed)
1276{
1277 // We want to export the data in the form of a matrix, exactly as the data
1278 // appear within the colormap, unless the color is replaced with the intensity
1279 // value.
1280
1281 // We want to limit the export to the visible data range in the plot widget.
1282
1283 QCPColorMap *color_map_p = static_cast<QCPColorMap *>(plottable(0));
1284 QCPColorMapData *map_data = color_map_p->data();
1285
1286 int key_index_lower_range;
1287 int key_index_upper_range;
1288 currentXaxisRangeIndices(key_index_lower_range, key_index_upper_range);
1289
1290 // qDebug() << "Cell indices for currently visible key range:"
1291 //<< key_index_lower_range << "-" << key_index_upper_range;
1292
1293 int value_index_lower_range;
1294 int value_index_upper_range;
1295 currentYaxisRangeIndices(value_index_lower_range, value_index_upper_range);
1296
1297 // qDebug() << "Cell indices for currently visible value range:"
1298 //<< value_index_lower_range << "-" << value_index_upper_range;
1299
1300 data_string.clear();
1301
1302 // At this point, we can write the header of the key data (that is the dt
1303 // key values).
1304
1305 for(int key_iter = key_index_lower_range; key_iter < key_index_upper_range;
1306 ++key_iter)
1307 {
1308 double current_key_value;
1309 map_data->cellToCoord(key_iter, 0, &current_key_value, nullptr);
1310
1311 data_string += QString("%1 ").arg(current_key_value, 0, 'f', 6, ' ');
1312 }
1313
1314 // Finally call the newline
1315 data_string += "\n";
1316
1317 // Now fill in the matrix, from top to down, that is from higher m/z values to
1318 // lower values.
1319
1320 // The matrix we are exporting looks like this:
1321
1322 // |
1323 // |
1324 // |
1325 // |
1326 // |
1327 // |
1328 // m/z |
1329 // |
1330 // |
1331 // |
1332 // |
1333 // |______________________________
1334 // dt
1335
1336 // Because we want the matrix to be presented the same, we need to fill in the
1337 // matrix from top to bottom starting from higher m/z values.
1338
1339 for(int value_iter = value_index_upper_range;
1340 value_iter >= value_index_lower_range;
1341 --value_iter)
1342 {
1343
1344 for(int key_iter = key_index_lower_range;
1345 key_iter < key_index_upper_range;
1346 ++key_iter)
1347 {
1348 double intensity = map_data->cell(key_iter, value_iter);
1349
1350 // Only to report debug messages
1351 double key_double;
1352 double value_double;
1353 map_data->cellToCoord(
1354 key_iter, value_iter, &key_double, &value_double);
1355
1356 // qDebug() << "Currently iterated cell: " << key_iter << ","
1357 //<< value_iter << "with values:" << key_double << ","
1358 //<< value_double << "with intensity:" << intensity;
1359
1360 // The intensity without decimals
1361 if(detailed)
1362 data_string += QString("%1/%2/%3 ")
1363 .arg(key_double, 0, 'f', 6, ' ')
1364 .arg(value_double, 0, 'f', 6, ' ')
1365 .arg(intensity);
1366 else
1367 data_string += QString("%1 ").arg(intensity, 0, 'f', 0, ' ');
1368 }
1369
1370 data_string += "\n";
1371 }
1372
1373 // qDebug().noquote() << "The matrix: " << data_string;
1374 // qDebug() << "The completed data string has size: " <<
1375 // data_string.size();
1376
1377 data_string += "\n";
1378}
1379
1380
1381} // namespace pappso
void dataToMatrixString(QString &data_string, bool detailed=false)
void currentYaxisRangeIndices(int &lower, int &upper)
virtual QColor getPlottingColor(int index=0) const override
ColorMapPlotConfig * mpa_origColorMapPlotConfig
void dataTo3ColString(QString &data_string)
virtual void zAxisFilterLowPassThreshold(double threshold)
fix maximum value for the intensity
const ColorMapPlotConfig * getOrigColorMapPlotConfig()
void currentXaxisRangeIndices(int &lower, int &upper)
virtual void setColorMapPlotConfig(const ColorMapPlotConfig &color_map_config)
virtual void setPlottingColor(QCPAbstractPlottable *plottable_p, const QColor &new_color) override
virtual const ColorMapPlotConfig & getColorMapPlotConfig()
virtual QCPColorMap * addColorMap(std::shared_ptr< std::map< double, MapTrace > > double_map_trace_map_sp, const ColorMapPlotConfig color_map_plot_config, const QColor &color)
virtual void zAxisFilterHighPassPercentage(double threshold_percentage)
virtual ~BaseColorMapPlotWidget()
Destruct this BaseColorMapPlotWidget instance.
virtual void zAxisFilterLowPassPercentage(double threshold_percentage)
virtual void createAllAncillaryItems()
virtual void resetAxesRangeHistory()
void plottableSelectionChangedSignal(QCPAbstractPlottable *plottable_p, bool selected)
BasePlotContext m_context
virtual std::size_t getTotalNumberOfScans() const
get the number of scans contained in this frame each scan represents an ion mobility slice
virtual std::vector< quint32 > getScanIntensityList(std::size_t scanNum) const override
get raw intensities without transformation from one scan it needs intensity normalization
virtual std::vector< quint32 > getScanTofIndexList(std::size_t scanNum) const override
get raw index list for one given scan index are not TOF nor m/z, just index on digitizer
tries to keep as much as possible monoisotopes, removing any possible C13 peaks and changes multichar...
Definition aa.cpp:39
AxisScale
Definition types.h:236
DataKind
Definition types.h:218
void setOrigAndLastMaxZValue(double value)
void setOrigAndLastMinZValue(double value)