OpenMS  3.0.0
Plot1DCanvas.h
Go to the documentation of this file.
1 // --------------------------------------------------------------------------
2 // OpenMS -- Open-Source Mass Spectrometry
3 // --------------------------------------------------------------------------
4 // Copyright The OpenMS Team -- Eberhard Karls University Tuebingen,
5 // ETH Zurich, and Freie Universitaet Berlin 2002-2022.
6 //
7 // This software is released under a three-clause BSD license:
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of any author or any participating institution
14 // may be used to endorse or promote products derived from this software
15 // without specific prior written permission.
16 // For a full list of authors, refer to the file AUTHORS.
17 // --------------------------------------------------------------------------
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING
22 // INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // --------------------------------------------------------------------------
31 // $Maintainer: Timo Sachsenberg$
32 // $Authors: Marc Sturm, Timo Sachsenberg, Chris Bielow $
33 // --------------------------------------------------------------------------
34 
35 #pragma once
36 
37 // OpenMS_GUI config
38 #include <OpenMS/VISUAL/OpenMS_GUIConfig.h>
39 
40 // OpenMS
45 
46 // QT
47 #include <QTextDocument>
48 #include <QPoint>
49 
50 // STL
51 #include <vector>
52 #include <utility>
53 
54 // QT
55 class QAction;
56 
57 namespace OpenMS
58 {
59  class Annotation1DItem;
60 
67  class Gravitator
68  {
69  public:
70 
72 
78  {
79  setGravityAxis(axis);
80  }
81 
86  Gravitator(const DimMapper<2>& unit_mapper)
87  {
88  setIntensityAsGravity(unit_mapper);
89  }
90 
96  void setGravityAxis(DIM axis)
97  {
98  if (axis != DIM::X && axis != DIM::Y)
99  {
100  throw Exception::InvalidValue(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Not a valid axis for 1D plotting", String((int)axis));
101  }
102  gravity_axis_ = axis;
103  }
104 
110  void setIntensityAsGravity(const DimMapper<2>& unit_mapper)
111  {
112  if (unit_mapper.getDim(DIM::X).getUnit() == DIM_UNIT::INT)
113  {
115  }
116  if (unit_mapper.getDim(DIM::Y).getUnit() == DIM_UNIT::INT)
117  {
119  }
121  throw Exception::NotImplemented(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION);
122  }
123 
126  {
127  return gravity_axis_;
128  }
129 
134  Gravitator swap() const
135  {
136  auto r = *this;
137  r.setGravityAxis( (r.getGravityAxis() == DIM::X) ? DIM::Y : DIM::X);
138  return r;
139  }
140 
146  QPoint gravitateMin(QPoint p, const AreaXYType& area) const
147  {
148  if (gravity_axis_ == DIM::X)
149  {
150  p.rx() = area.minX();
151  }
152  else if (gravity_axis_ == DIM::Y)
153  {
154  p.ry() = area.minY();
155  }
156  return p;
157  }
158 
164  QPoint gravitateWith(QPoint p, const QPoint& delta) const
165  {
166  if (gravity_axis_ == DIM::X)
167  {
168  p.rx() += delta.x();
169  }
170  else if (gravity_axis_ == DIM::Y)
171  {
172  p.ry() += delta.y();
173  }
174  return p;
175  }
176 
178  template<UInt D>
180  {
181  p[(int)gravity_axis_] += delta[(int)gravity_axis_];
182  return p;
183  }
184 
190  QPoint gravitateTo(QPoint p, const QPoint& target) const
191  {
192  if (gravity_axis_ == DIM::X)
193  {
194  p.rx() = target.x();
195  }
196  else if (gravity_axis_ == DIM::Y)
197  {
198  p.ry() = target.y();
199  }
200  return p;
201  }
202 
204  template<UInt D>
206  {
207  p[(int)gravity_axis_] = target[(int)gravity_axis_];
208  return p;
209  }
210 
211 
213  QPoint gravitateMax(QPoint p, const AreaXYType& area) const
214  {
215  if (gravity_axis_ == DIM::X)
216  {
217  p.rx() = area.maxX();
218  }
219  else if (gravity_axis_ == DIM::Y)
220  {
221  p.ry() = area.maxY();
222  }
223  return p;
224  }
225 
230  QPoint gravitateZero(QPoint p) const
231  {
232  if (gravity_axis_ == DIM::X)
233  {
234  p.rx() = 0;
235  }
236  else if (gravity_axis_ == DIM::Y)
237  {
238  p.ry() = 0;
239  }
240  return p;
241  }
242 
247  template<UInt D>
249  {
250  p[(int)gravity_axis_] = 0;
251  return p;
252  }
253 
258  template<UInt D>
260  {
261  p[(int)gravity_axis_] = std::numeric_limits<float>::quiet_NaN();
262  return p;
263  }
264 
269  int gravityValue(const QPoint& p) const
270  {
271  if (gravity_axis_ == DIM::X)
272  {
273  return p.x();
274  }
275  else if (gravity_axis_ == DIM::Y)
276  {
277  return p.y();
278  }
279  // never reached, but make compilers happy
280  return 0;
281  }
286  template<UInt D>
287  int gravityValue(const DPosition<D>& p) const
288  {
289  return p[(int)gravity_axis_];
290  }
291 
297  template<UInt D>
298  auto gravityDiff(const DPosition<D>& start, const DPosition<D>& end) const
299  {
300  return end[(int)gravity_axis_] - start[(int)gravity_axis_];
301  }
302 
303  private:
306  };
307 
319  class OPENMS_GUI_DLLAPI Plot1DCanvas :
320  public PlotCanvas
321  {
322  Q_OBJECT
323 
324 public:
327  {
331  LM_XPERCENT_YPERCENT
332  };
333 
335  constexpr static double TOP_MARGIN{1.09};
336 
338  Plot1DCanvas(const Param& preferences, const DIM gravity_axis = DIM::Y, QWidget* parent = nullptr);
340  ~Plot1DCanvas() override;
341 
344  const LayerData1DBase& getLayer(Size index) const;
347  LayerData1DBase& getLayer(Size index);
348 
351  const LayerData1DBase& getCurrentLayer() const;
354  LayerData1DBase& getCurrentLayer();
355 
357  const DimBase& getGravityDim() const;
358 
360  const DimBase& getNonGravityDim() const;
361 
371  bool addChromLayer(ExperimentSharedPtrType chrom_exp_sptr,
372  ODExperimentSharedPtrType ondisc_sptr,
373  OSWDataSharedPtrType chrom_annotation,
374  const int index,
375  const String& filename,
376  const String& caption);
377 
378 
381  {
383  DM_CONNECTEDLINES
384  };
385 
387  DrawModes getDrawMode() const;
388 
390  void setDrawMode(DrawModes mode);
391 
392  // Docu in base class
393  void showCurrentLayerPreferences() override;
394 
396  bool flippedLayersExist();
397 
399  void flipLayer(Size index);
400 
402  bool mirrorModeActive() const;
403 
405  void setMirrorModeActive(bool b);
406 
408  void dataToWidget(const DPosition<2>& peak, QPoint& point, bool flipped = false);
410  void dataToWidget(const DPosition<2>& xy_point, DPosition<2>& point, bool flipped);
411 
413  void dataToWidget(double x, double y, QPoint& point, bool flipped = false);
414 
416  PointXYType widgetToData(const QPoint& pos);
417 
419  PointXYType widgetToData(double x, double y);
420 
424  inline void dataToWidgetDistance(double x, double y, QPoint& point)
425  {
426  dataToWidget_(x, y, point);
427  // subtract the 'offset'
428  QPoint zero;
429  dataToWidget_(0, 0, zero);
430  point -= zero;
431  }
432 
436  inline PointXYType widgetToDataDistance(double x, double y)
437  {
438  PointXYType point = widgetToData_(x, y);
439  // subtract the 'offset'
440  PointXYType zero = widgetToData_(0, 0);
441  point -= zero;
442  return point;
443  }
444 
451  template <class T>
452  void pushIntoDataRange(T& data_point, const int layer_index)
453  { // note: if this is needed for anything other than the 1D Canvas, you need to make sure to call the correct widgetToData/ etc functions --- they work a bit different, depending on Canvas
454  auto xy_unit = unit_mapper_.map(data_point); // datatype to xy
455  pushIntoDataRange(xy_unit, layer_index);
456  unit_mapper_.fromXY(xy_unit, data_point); // xy to datatype
457  }
458 
464  //template<> // specialization does not compile when declared within the class on GCC -- even though it should; but I'm not moving it outside! :)
465  void pushIntoDataRange(PointXYType& xy_unit, const int layer_index)
466  { // note: if this is needed for anything other than the 1D Canvas, you need to make sure to call the correct widgetToData/ etc functions --- they work a bit different, depending on Canvas
467  auto p_range = unit_mapper_.fromXY(xy_unit);
468  const auto all_range = getLayer(layer_index).getRange();
469  p_range.pushInto(all_range);
470  xy_unit = unit_mapper_.mapRange(p_range).minPosition();
471  }
472 
474  void setTextBox(const QString& html);
475 
477 
479  Annotation1DItem* addPeakAnnotation(const PeakIndex& peak_index, const QString& text, const QColor& color);
480 
483  void performAlignment(Size layer_index_1, Size layer_index_2, const Param& param);
484 
486  void resetAlignment();
487 
489  Size getAlignmentSize();
490 
492  double getAlignmentScore() const;
493 
495  std::vector<std::pair<Size, Size> > getAlignedPeaksIndices();
496 
498  void activateSpectrum(Size index, bool repaint = true);
499 
501  void setCurrentLayerPeakPenStyle(Qt::PenStyle ps);
502 
504  void paint(QPainter* paint_device, QPaintEvent* e);
505 
507  void setDrawInterestingMZs(bool enable);
508 
510  bool isDrawInterestingMZs() const;
511 
512  // Show/hide ion ladder on top right corner (Identification view)
513  void setIonLadderVisible(bool show);
514 
515  // Returns true if ion ladder is visible
516  bool isIonLadderVisible() const;
517 
522  const Gravitator& getGravitator() const
523  {
524  return gr_;
525  }
526 
527 signals:
529  void showCurrentPeaksAs2D();
530 
532  void showCurrentPeaksAs3D();
533 
535  void showCurrentPeaksAsIonMobility(const MSSpectrum& spec);
536 
538  void showCurrentPeaksAsDIA(const Precursor& pc, const MSExperiment& exp);
539 
540 public slots:
541  // Docu in base class
542  void activateLayer(Size layer_index) override;
543  // Docu in base class
544  void removeLayer(Size layer_index) override;
545  // Docu in base class
546  void updateLayer(Size i) override;
547  // Docu in base class
548  void horizontalScrollBarChange(int value) override;
549 
550 protected slots:
551 
553  void currentLayerParamtersChanged_();
554 
555 protected:
556 
557 
566  void dataToWidget_(double x, double y, QPoint& point)
567  {
568  const auto& xy = visible_area_.getAreaXY();
569  const auto h_px = height();
570  const auto w_px = width();
571 
572  point.setX(int((x - xy.minX()) / xy.width() * w_px));
573 
574  if (intensity_mode_ != PlotCanvas::IM_LOG)
575  {
576  point.setY(int((xy.maxY() - y) / xy.height() * h_px));
577  }
578  else // IM_LOG
579  {
580  point.setY(h_px - int(std::log10((y - xy.minY()) + 1) / std::log10(xy.height() + 1) * h_px));
581  }
582  }
583 
584  void dataToWidget_(const DPosition<2>& xy, QPoint& point)
585  {
586  dataToWidget_(xy.getX(), xy.getY(), point);
587  }
588 
589  QPoint dataToWidget_(const DPosition<2>& xy)
590  {
591  QPoint point;
592  dataToWidget_(xy.getX(), xy.getY(), point);
593  return point;
594  }
595 
596  // Docu in base class
597  bool finishAdding_() override;
598 
600  void drawCoordinates_(QPainter& painter, const PeakIndex& peak);
602  void drawDeltas_(QPainter& painter, const PeakIndex& start, const PeakIndex& end);
603 
605  void drawAlignment_(QPainter& painter);
606 
612  void changeVisibleArea_(const AreaXYType& new_area, bool repaint = true, bool add_to_stack = false);
613 
619  void changeVisibleArea_(const UnitRange& new_area, bool repaint = true, bool add_to_stack = false);
620 
621 
623  void drawHighlightedPeak_(Size layer_index, const PeakIndex& peak, QPainter& painter, bool draw_elongation = false);
624 
626  void updatePercentageFactor_(Size layer_index);
627 
628  // Docu in base class
629  void recalculateSnapFactor_() override;
630  // Docu in base class
631  void updateScrollbars_() override;
632  // Docu in base class
633  void intensityModeChange_() override;
634 
635 
638  void paintEvent(QPaintEvent* e) override;
639  void mousePressEvent(QMouseEvent* e) override;
640  void mouseReleaseEvent(QMouseEvent* e) override;
641  void mouseMoveEvent(QMouseEvent* e) override;
642  void keyPressEvent(QKeyEvent* e) override;
643  void contextMenuEvent(QContextMenuEvent* e) override;
645 
646  // docu in base class
647  void zoomForward_() override;
648  // docu in base class
649  void zoom_(int x, int y, bool zoom_in) override;
650  // docu in base class
651  void translateLeft_(Qt::KeyboardModifiers m) override;
652  // docu in base class
653  void translateRight_(Qt::KeyboardModifiers m) override;
654  // docu in base class
655  void translateForward_() override;
656  // docu in base class
657  void translateBackward_() override;
658 
659  // docu in base class
660  void paintGridLines_(QPainter& painter) override;
661 
663  PeakIndex findPeakAtPosition_(QPoint);
664 
666  void addUserLabelAnnotation_(const QPoint& screen_position);
668  void addLabelAnnotation_(const QPoint& screen_position, const QString& label_text);
670  void addUserPeakAnnotation_(PeakIndex near_peak);
671 
673  void ensureAnnotationsWithinDataRange_();
674 
675  friend class Painter1DChrom;
676  friend class Painter1DPeak;
677  friend class Painter1DIonMobility;
678 
682 
684  std::vector<DrawModes> draw_modes_;
686  std::vector<Qt::PenStyle> peak_penstyle_;
687 
691  bool mirror_mode_ = false;
693  bool moving_annotations_ = false;
695  bool show_alignment_ = false;
701  std::vector<std::pair<double, double> > aligned_peaks_mz_delta_;
703  std::vector<std::pair<Size, Size> > aligned_peaks_indices_;
705  double alignment_score_ = 0.0;
707  bool ion_ladder_visible_ = true;
709  bool draw_interesting_MZs_ = false;
711  QTextDocument text_box_content_;
714  };
715 
716 
717 
718 
719 } // namespace OpenMS
720 
An abstract class acting as an interface for the different 1D annotation items.
Definition: Annotation1DItem.h:61
void dataToWidget_(const DPosition< 2 > &xy, QPoint &point)
Definition: Plot1DCanvas.h:584
std::vector< Qt::PenStyle > peak_penstyle_
Draw style (for each layer)
Definition: Plot1DCanvas.h:686
Size alignment_layer_1_
Layer index of the first alignment layer.
Definition: Plot1DCanvas.h:697
A more convenient string class.
Definition: String.h:58
std::vector< DrawModes > draw_modes_
Draw modes (for each layer) - sticks or connected lines.
Definition: Plot1DCanvas.h:684
Precursor meta information.
Definition: Precursor.h:58
std::vector< std::pair< Size, Size > > aligned_peaks_indices_
Stores the peak indices of pairs of aligned peaks in both spectra.
Definition: Plot1DCanvas.h:703
CoordinateType maxX() const
Accessor for min_ coordinate maximum.
Definition: DIntervalBase.h:306
Gravitator(DIM axis)
C&#39;tor to apply gravity on any axis.
Definition: Plot1DCanvas.h:77
Canvas for visualization of one or several spectra.
Definition: Plot1DCanvas.h:319
void dataToWidgetDistance(double x, double y, QPoint &point)
converts a distance in axis values to pixel values
Definition: Plot1DCanvas.h:424
DPosition< D > gravitateWith(DPosition< D > p, const DPosition< D > &delta) const
Same as gravitateWith()
Definition: Plot1DCanvas.h:179
Gravitator swap() const
Swap gravity axis (from X to Y, or vice versa)
Definition: Plot1DCanvas.h:134
Definition: Plot1DCanvas.h:329
int gravityValue(const QPoint &p) const
Definition: Plot1DCanvas.h:269
boost::shared_ptr< OSWData > OSWDataSharedPtrType
SharedPtr on OSWData.
Definition: LayerDataChrom.h:42
CoordinateType getY() const
Name accessor for the second dimension. Only for DPosition<2>, for visualization. ...
Definition: DPosition.h:164
Main OpenMS namespace.
Definition: FeatureDeconvolution.h:47
QPoint gravitateMax(QPoint p, const AreaXYType &area) const
Opposite of gravitateMin()
Definition: Plot1DCanvas.h:213
draw data as peak
Definition: Plot1DCanvas.h:382
Definition: Plot1DCanvas.h:328
Base class for all 1D layers, a special case of LayerData.
Definition: LayerData1DBase.h:53
CoordinateType getX() const
Name accessor for the first dimension. Only for DPosition<2>, for visualization.
Definition: DPosition.h:157
void setIntensityAsGravity(const DimMapper< 2 > &unit_mapper)
Convenience function, which picks the Intensity dimension from a DimMapper as gravity axis...
Definition: Plot1DCanvas.h:110
The representation of a 1D spectrum.
Definition: MSSpectrum.h:66
DPosition< D > gravitateTo(DPosition< D > p, const DPosition< D > &target) const
Same as gravitateTo()
Definition: Plot1DCanvas.h:205
void pushIntoDataRange(T &data_point, const int layer_index)
Pushes a data point back into the valid data range of the current layer area. Useful for annotation i...
Definition: Plot1DCanvas.h:452
PointXYType widgetToDataDistance(double x, double y)
compute distance in widget coordinates (unit axis as shown) when moving x/y pixel in chart coordinate...
Definition: Plot1DCanvas.h:436
QPoint gravitateMin(QPoint p, const AreaXYType &area) const
Definition: Plot1DCanvas.h:146
QPoint measurement_start_point_px_
start point of "ruler" in pixel coordinates for measure mode
Definition: Plot1DCanvas.h:689
const Gravitator & getGravitator() const
Get gravity manipulation object to apply gravity to points.
Definition: Plot1DCanvas.h:522
QPoint gravitateTo(QPoint p, const QPoint &target) const
Definition: Plot1DCanvas.h:190
LabelMode
Label modes (percentage or absolute) of x axis and y axis.
Definition: Plot1DCanvas.h:326
const DimBase & getDim(DIM d) const
obtain unit/name for X/Y/Z dimension.
Definition: DimMapper.h:765
A base class for a dimension which represents a certain unit (e.g. RT or m/z). Derived classes implem...
Definition: DimMapper.h:66
int gravityValue(const DPosition< D > &p) const
Definition: Plot1DCanvas.h:287
Logarithmic mode.
Definition: PlotCanvas.h:209
DPosition< D > gravitateNAN(DPosition< D > p) const
Definition: Plot1DCanvas.h:259
QTextDocument text_box_content_
The text box in the upper left corner with the current data coordinates of the cursor.
Definition: Plot1DCanvas.h:711
auto gravityDiff(const DPosition< D > &start, const DPosition< D > &end) const
Definition: Plot1DCanvas.h:298
CoordinateType minY() const
Accessor for max_ coordinate minimum.
Definition: DIntervalBase.h:300
CoordinateType maxY() const
Accessor for max_ coordinate maximum.
Definition: DIntervalBase.h:312
DIM
Definition: DimMapper.h:607
Painter1D for mobilograms.
Definition: Painter1DBase.h:155
Management and storage of parameters / INI files.
Definition: Param.h:69
Invalid value exception.
Definition: Exception.h:327
In-Memory representation of a mass spectrometry run.
Definition: MSExperiment.h:70
DPosition< D > gravitateZero(DPosition< D > p) const
Definition: Plot1DCanvas.h:248
DIM gravity_axis_
Where are points in the X-Y plane projected onto when drawing lines?
Definition: Plot1DCanvas.h:305
DIM_UNIT getUnit() const
The unit of the dimension.
Definition: DimMapper.h:152
size_t Size
Size type e.g. used as variable which can hold result of size()
Definition: Types.h:127
std::vector< std::pair< double, double > > aligned_peaks_mz_delta_
Stores the alignment as MZ values of pairs of aligned peaks in both spectra.
Definition: Plot1DCanvas.h:701
CoordinateType minX() const
Accessor for min_ coordinate minimum.
Definition: DIntervalBase.h:294
Definition: Plot1DCanvas.h:330
QPoint dataToWidget_(const DPosition< 2 > &xy)
Definition: Plot1DCanvas.h:589
void pushIntoDataRange(PointXYType &xy_unit, const int layer_index)
Pushes a data point back into the valid data range of the current layer area. Useful for annotation i...
Definition: Plot1DCanvas.h:465
DRange< N_DIM > AreaXYType
The Area in X,Y,(Z)... dimension (number of dimensions depends on N_DIM)
Definition: DimMapper.h:803
Size alignment_layer_2_
Layer index of the second alignment layer.
Definition: Plot1DCanvas.h:699
void dataToWidget_(double x, double y, QPoint &point)
Convert chart to widget coordinates.
Definition: Plot1DCanvas.h:566
DIM getGravityAxis() const
Which axis is affected by gravity?
Definition: Plot1DCanvas.h:125
Base class for visualization canvas classes.
Definition: PlotCanvas.h:145
QPoint gravitateWith(QPoint p, const QPoint &delta) const
Definition: Plot1DCanvas.h:164
void setGravityAxis(DIM axis)
Definition: Plot1DCanvas.h:96
Manipulates X or Y component of points in the X-Y plane, by assuming one axis (either X or Y axis) ha...
Definition: Plot1DCanvas.h:67
Painter1D for spectra.
Definition: Painter1DBase.h:118
DrawModes
Enumerate all available paint styles.
Definition: Plot1DCanvas.h:380
Painter1D for chromatograms.
Definition: Painter1DBase.h:138
Not implemented exception.
Definition: Exception.h:428
Gravitator(const DimMapper< 2 > &unit_mapper)
Convenience c&#39;tor, which picks the Intensity dimension from a DimMapper as gravity axis...
Definition: Plot1DCanvas.h:86
Index of a peak or feature.
Definition: PeakIndex.h:50
QPoint gravitateZero(QPoint p) const
Definition: Plot1DCanvas.h:230
Gravitator gr_
handles pulling/pushing of points to the edges of the widget
Definition: Plot1DCanvas.h:713