libpappsomspp
Library for mass spectrometry
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
35 #include "basecolormapplotwidget.h"
36 #include "../../trace/maptrace.h"
37 #include "../../pappsoexception.h"
38 
39 
40 namespace 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 
71 //! Destruct \c this BaseColorMapPlotWidget instance.
72 /*!
73 
74  The destruction involves clearing the history, deleting all the axis range
75  history items for x and y axes.
76 
77 */
79 {
80 }
81 
82 
83 void
85  const ColorMapPlotConfig &color_map_config)
86 {
87  m_colorMapPlotConfig = color_map_config;
88 }
89 
90 
91 const ColorMapPlotConfig &
93 {
94  return m_colorMapPlotConfig;
95 }
96 
97 
98 QCPColorMap *
100  std::shared_ptr<std::map<double, MapTrace>> double_map_trace_map_sp,
101  ColorMapPlotConfig color_map_plot_config,
102  const QColor &color)
103 {
104  // qDebug() << "Adding color map with config:" <<
105  // color_map_plot_config.toString();
106 
107  if(!color.isValid())
108  throw PappsoException(
109  QString("The color to be used for the plot graph is invalid."));
110 
111  QCPColorMap *color_map_p = new QCPColorMap(xAxis, yAxis);
112 
113  color_map_p->setLayer("plotsLayer");
114 
115  // Do not forget to copy the config!
116 
117  m_colorMapPlotConfig = color_map_plot_config;
118 
119 #if 0
120  // This is the code on the QCustomPlot documentation and it works fine.
121  QCPColorMap *color_map_p = new QCPColorMap(xAxis, yAxis);
122 
123  color_map_p->data()->setSize(50, 50);
124  color_map_p->data()->setRange(QCPRange(0, 2), QCPRange(0, 2));
125  for(int x = 0; x < 50; ++x)
126  for(int y = 0; y < 50; ++y)
127  color_map_p->data()->setCell(x, y, qCos(x / 10.0) + qSin(y / 10.0));
128  color_map_p->setGradient(QCPColorGradient::gpPolar);
129  color_map_p->rescaleDataRange(true);
130  rescaleAxes();
131  replot();
132 #endif
133 
134  // Only now can afford to call createAllAncillaryItems() in this derived class
135  // because the color map has been created already. The rendering order will
136  // thus not hide the ancillary items, since they have been created after the
137  // color map plot (since the rendering order is according to the
138  // order in which the items have been created). See contructor note.
140 
141  // Connect the signal of selection change so that we can re-emit it for the
142  // widget that is using *this widget.
143 
144  connect(color_map_p,
145  static_cast<void (QCPAbstractPlottable::*)(bool)>(
146  &QCPAbstractPlottable::selectionChanged),
147  [this, color_map_p]() {
148  emit plottableSelectionChangedSignal(color_map_p,
149  color_map_p->selected());
150  });
151 
152  // qDebug() << "Configuring the color map with this config:"
153  //<< color_map_plot_config.toString();
154 
155  color_map_p->data()->setSize(color_map_plot_config.keyCellCount,
156  color_map_plot_config.mzCellCount);
157 
158  color_map_p->data()->setRange(QCPRange(color_map_plot_config.minKeyValue,
159  color_map_plot_config.maxKeyValue),
160  QCPRange(color_map_plot_config.minMzValue,
161  color_map_plot_config.maxMzValue));
162  color_map_p->data()->fill(0.0);
163 
164  // We have now to fill the color map.
165 
166  for(auto &&pair : *double_map_trace_map_sp)
167  {
168 
169  // The first value is the key and the second value is the MapTrace into
170  // which we need to iterated and for each point (double mz, double
171  // intensity) create a map cell.
172 
173  double dt_or_rt_key = pair.first;
174  MapTrace map_trace = pair.second;
175 
176  for(auto &&data_point_pair : map_trace)
177  {
178  double mz = data_point_pair.first;
179  double intensity = data_point_pair.second;
180 
181  // We are filling dynamically the color map. If a cell had already
182  // something in, then we need to take that into account. This is
183  // because we let QCustomPlot handle the fuzzy transition between
184  // color map plot cells.
185 
186  double prev_intensity = color_map_p->data()->data(dt_or_rt_key, mz);
187 
188  // qDebug() << "Setting tri-point:" << dt_or_rt_key << "," << mz <<
189  // ","
190  //<< prev_intensity + intensity;
191 
192  color_map_p->data()->setData(
193  dt_or_rt_key, mz, prev_intensity + intensity);
194  }
195  }
196 
197  // At this point we have finished filling-up the color map.
198 
199  // The gpThermal is certainly one of the best.
200 
201  color_map_p->setGradient(QCPColorGradient::gpThermal);
202 
203  color_map_p->rescaleDataRange(true);
204 
205  color_map_p->rescaleAxes();
207 
208  // The pen of the color map itself is of no use. Instead the user will see the
209  // color of the axes' labels.
210 
211  QPen pen = xAxis->basePen();
212  pen.setColor(color);
213 
214  xAxis->setBasePen(pen);
215  xAxis->setLabelColor(color);
216  xAxis->setTickLabelColor(color);
217 
218  yAxis->setBasePen(pen);
219  yAxis->setLabelColor(color);
220  yAxis->setTickLabelColor(color);
221 
222  // And now set the color map's pen to the same color, even if we do not use
223  // it, we need it for coloring the plots that might be integrated from this
224  // color map.
225 
226  color_map_p->setPen(pen);
227 
228  // Copy the color map's data into a backup copy.
229 
230  mpa_backupColorMapData = new QCPColorMapData(*(color_map_p->data()));
231 
232  replot();
233 
234  return color_map_p;
235 }
236 
237 
238 void
240 {
241  // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()" ;
242 
243  QCPColorMap *color_map_p = static_cast<QCPColorMap *>(plottable(0));
244 
245  QCPColorMapData *origData = color_map_p->data();
246 
247  int keySize = origData->keySize();
248  int valueSize = origData->valueSize();
249 
250  // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()"
251  //<< "Orig data size:" << keySize << valueSize;
252 
253  QCPRange keyRange = origData->keyRange();
254  QCPRange valueRange = origData->valueRange();
255 
256  // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()"
257  //<< "Value at cell 80,650:" << origData->cell(80,650);
258 
259  // Transposed map.
260  QCPColorMapData *newData =
261  new QCPColorMapData(valueSize, keySize, valueRange, keyRange);
262 
263  for(int iter = 0; iter < keySize; ++iter)
264  {
265  for(int jter = 0; jter < valueSize; ++jter)
266  {
267  double cellData = origData->cell(iter, jter);
268 
269  newData->setCell(jter, iter, cellData);
270  }
271  }
272 
273  // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()"
274  //<< "New data size:" << newData->keySize() << newData->valueSize();
275 
276  // At this point the transposition has been done.
277 
278  color_map_p->data()->clear();
279  color_map_p->rescaleDataRange(true);
280 
281  // Now we need to invert the labels and data kinds.
282 
285  m_colorMapPlotConfig.yAxisDataKind = temp_data_kind;
286 
287  QString temp_axis_label = xAxis->label();
288  xAxis->setLabel(yAxis->label());
289  yAxis->setLabel(temp_axis_label);
290 
291  // Will take ownership of the newData.
292  color_map_p->setData(newData);
293 
294  // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()"
295  //<< "Value at cell 80,650:" << newData->cell(80,650)
296  //<< "Value at cell 650, 80:" << newData->cell(650,80);
297 
298  // QCPAxis *p_keyAxis = mp_colorMap->keyAxis();
299  // QCPAxis *p_valueAxis = mp_colorMap->valueAxis();
300 
301  // mp_colorMap->setKeyAxis(p_valueAxis);
302  // mp_colorMap->setValueAxis(p_keyAxis);
303 
304  color_map_p->rescaleAxes();
305 
306  replot();
307 }
308 
309 
310 void
312 {
313  // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()" ;
314 
316  {
317  qDebug() << "Asking to change z axis scale to log10 while it is already "
318  "like so.";
319 
320  return;
321  }
322 
323  QCPColorMap *color_map_p = static_cast<QCPColorMap *>(plottable(0));
324 
325  QCPColorMapData *origData = color_map_p->data();
326 
327  int keySize = origData->keySize();
328  int valueSize = origData->valueSize();
329 
330  QCPRange keyRange = origData->keyRange();
331  QCPRange valueRange = origData->valueRange();
332 
333  // Log-ified heat map.
334  QCPColorMapData *newData =
335  new QCPColorMapData(keySize, valueSize, keyRange, valueRange);
336 
337  for(int iter = 0; iter < keySize; ++iter)
338  {
339  for(int jter = 0; jter < valueSize; ++jter)
340  {
341  double cell_data = origData->cell(iter, jter);
342 
343  double new_cell_data = 0;
344 
345  if(!cell_data)
346  // The log10 would be -inf, but then we'd have a huge data range and
347  // the color map would look totally blue... that is like 0 intensity
348  // all over.
349  new_cell_data = -1;
350  else
351  new_cell_data = std::log10(cell_data);
352 
353  // qDebug() << "cell_data:" << cell_data
354  //<< "new_cell_data:" << new_cell_data;
355 
356  newData->setCell(iter, jter, new_cell_data);
357  }
358  }
359 
360  color_map_p->data()->clear();
361  // Now we need to document the change.
362 
364 
365  // Will take ownership of the newData.
366  color_map_p->setData(newData);
367 
368  color_map_p->data()->recalculateDataBounds();
369  color_map_p->rescaleDataRange(true);
370 
371  // We should not do this, as the user might have zoomed to a region of
372  // interest.
373  // color_map_p->rescaleAxes();
374 
375  replot();
376 }
377 
378 
379 void
381 {
382  QCPColorMap *color_map_p = static_cast<QCPColorMap *>(plottable(0));
383  color_map_p->data()->clear();
384 
385  if(mpa_backupColorMapData == nullptr)
386  throw(PappsoException(
387  "Not possible that the mpa_backupColorMapData pointer is null."));
388 
389  // We do no want that the color_map_p takes ownership of the data, because
390  // these must remain there always, so pass true, to say that we want to copy
391  // the data not transfer the pointer.
392  color_map_p->setData(mpa_backupColorMapData, true);
393 
394  color_map_p->data()->recalculateDataBounds();
395  color_map_p->rescaleDataRange(true);
396 
397  // We should not do this, as the user might have zoomed to a region of
398  // interest.
399  // color_map_p->rescaleAxes();
400 
402 
403  replot();
404 }
405 
406 
407 DataKind
409 {
411 }
412 
413 
414 DataKind
416 {
418 }
419 
420 
421 AxisScale
423 {
424  if(axis == Axis::x)
426  else if(axis == Axis::y)
428  else if(axis == Axis::z)
430  else
431  throw PappsoException(
432  QString("basecolormapplotwidget.cpp: The axis cannot be different than "
433  "x, y or z."));
434 
435  return AxisScale::unset;
436 }
437 
438 
439 AxisScale
441 {
443 }
444 
445 
446 AxisScale
448 {
450 }
451 
452 
453 AxisScale
455 {
457 }
458 
459 
460 void
461 BaseColorMapPlotWidget::setPlottingColor(QCPAbstractPlottable *plottable_p,
462  const QColor &new_color)
463 {
464  Q_UNUSED(plottable_p);
465 
466  // The pen of the color map itself is of no use. Instead the user will see the
467  // color of the axes' labels.
468 
469  QPen pen = xAxis->basePen();
470  pen.setColor(new_color);
471 
472  xAxis->setBasePen(pen);
473  xAxis->setLabelColor(new_color);
474  xAxis->setTickLabelColor(new_color);
475 
476  yAxis->setBasePen(pen);
477  yAxis->setLabelColor(new_color);
478  yAxis->setTickLabelColor(new_color);
479 
480  // And now set the color map's pen to the same color, even if we do not use
481  // it, we need it for coloring the plots that might be integrated from this
482  // color map.
483 
484  QCPColorMap *color_map_p = static_cast<QCPColorMap *>(plottable(0));
485 
486  color_map_p->setPen(pen);
487 
488  replot();
489 }
490 
491 
492 QColor
494 {
495  Q_UNUSED(index);
496 
497  QPen pen = xAxis->basePen();
498  return pen.color();
499 }
500 
501 
502 } // namespace pappso
virtual QColor getPlottingColor(int index=0) const override
virtual QCPColorMap * addColorMap(std::shared_ptr< std::map< double, MapTrace >> double_map_trace_map_sp, ColorMapPlotConfig color_map_plot_config, const QColor &color)
BaseColorMapPlotWidget(QWidget *parent, const QString &x_axis_label, const QString &y_axis_label)
virtual void setColorMapPlotConfig(const ColorMapPlotConfig &color_map_config)
virtual void setPlottingColor(QCPAbstractPlottable *plottable_p, const QColor &new_color) override
AxisScale axisScale(Axis axis) const
virtual const ColorMapPlotConfig & getColorMapPlotConfig()
virtual ~BaseColorMapPlotWidget()
Destruct this BaseColorMapPlotWidget instance.
virtual void createAllAncillaryItems()
virtual void resetAxesRangeHistory()
void plottableSelectionChangedSignal(QCPAbstractPlottable *plottable_p, bool selected)
tries to keep as much as possible monoisotopes, removing any possible C13 peaks and changes multichar...
Definition: aa.cpp:39
Axis
Definition: types.h:180
AxisScale
Definition: types.h:189
DataKind
Definition: types.h:171