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