File: xyplot.h

package info (click to toggle)
aoflagger 3.4.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 8,960 kB
  • sloc: cpp: 83,076; python: 10,187; sh: 260; makefile: 178
file content (188 lines) | stat: -rw-r--r-- 5,969 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#ifndef XYPLOT_H
#define XYPLOT_H

#include <gtkmm/drawingarea.h>

#include <stdexcept>
#include <string>

#include "legend.h"
#include "plotbase.h"
#include "system.h"
#include "title.h"
#include "xypointset.h"

enum class RangeDetermination { MinMaxRange, WinsorizedRange, SpecifiedRange };

class XYPlotAxis : public Axis {
 public:
  bool Show() const { return show_; }
  void SetShow(bool show) { show_ = show; }

  void SetMax(double max) {
    range_determination_ = RangeDetermination::SpecifiedRange;
    specified_max_ = max;
  }
  double SpecifiedMax() const { return specified_max_; }
  void SetMin(double min) {
    range_determination_ = RangeDetermination::SpecifiedRange;
    specified_min_ = min;
  }
  double SpecifiedMin() const { return specified_min_; }
  std::string SpecifiedDescription() const { return specified_description_; }
  void SetCustomDescription(const std::string& description) {
    specified_description_ = description;
  }
  void SetAutomaticDescription() { specified_description_ = std::string(); }
  void SetLogarithmic(bool logarithmic) { logarithmic_ = logarithmic; }
  bool Logarithmic() const { return logarithmic_; }
  void SetRangeDetermination(RangeDetermination range) {
    range_determination_ = range;
  }
  RangeDetermination GetRangeDetermination() const {
    return range_determination_;
  }

 private:
  bool logarithmic_ = false;
  bool show_ = true;
  double specified_min_ = 0.0;
  double specified_max_ = 0.0;
  RangeDetermination range_determination_ = RangeDetermination::MinMaxRange;
  std::string specified_description_;
};

class XYPlot final : public PlotBase {
 public:
  XYPlot();

  void Clear();

  // TODO
  bool ConvertToPlot(double screenX, double screenY, double& posX,
                     double& posY) const override {
    return false;
  }
  // TODO
  bool ConvertToScreen(double posX, double posY, double& screenX,
                       double& screenY) const override {
    return false;
  }

  XYPointSet& StartLine(
      const std::string& label, const std::string& xDesc = "x",
      const std::string& yDesc = "y",
      enum XYPointSet::DrawingStyle drawingStyle = XYPointSet::DrawLines);
  XYPointSet& StartLine(const std::string& label,
                        enum XYPointSet::DrawingStyle drawingStyle) {
    return StartLine(label, "x", "y", drawingStyle);
  }
  XYPointSet& StartLine() {
    return StartLine("", "x", "y", XYPointSet::DrawLines);
  }
  void PushDataPoint(double x, double y) {
    if (_pointSets.size() > 0)
      (*_pointSets.rbegin())->PushDataPoint(x, y);
    else
      throw std::runtime_error(
          "Trying to push a data point into a plot without point sets (call "
          "StartLine first).");
  }
  size_t PointSetCount() const { return _pointSets.size(); }
  XYPointSet& GetPointSet(size_t index) { return *_pointSets[index]; }
  const XYPointSet& GetPointSet(size_t index) const {
    return *_pointSets[index];
  }
  void SetIncludeZeroYAxis(bool includeZeroAxis) {
    _system.SetIncludeZeroYAxis(includeZeroAxis);
    if (includeZeroAxis) y_axis_.SetLogarithmic(false);
  }

  std::pair<double, double> RangeX(bool second_axis) const;
  std::pair<double, double> RangePositiveX(bool second_axis) const;
  std::pair<double, double> RangeY(bool second_axis) const;
  std::pair<double, double> RangePositiveY(bool second_axis) const;

  void SetShowAxisDescriptions(bool showAxisDescriptions) {
    _showAxisDescriptions = showAxisDescriptions;
  }
  bool ShowAxisDescriptions() const { return _showAxisDescriptions; }
  void SetTitle(const std::string& title) { _title.SetText(title); }
  void SavePdf(const std::string& filename, size_t width,
               size_t height) override;
  void SaveSvg(const std::string& filename, size_t width,
               size_t height) override;
  void SavePng(const std::string& filename, size_t width,
               size_t height) override;

  const std::string& GetTitle() const { return _title.Text(); }

  XYPlotAxis& XAxis() { return x_axis_; }
  const XYPlotAxis& XAxis() const { return x_axis_; }

  XYPlotAxis& YAxis() { return y_axis_; }
  const XYPlotAxis& YAxis() const { return y_axis_; }

  XYPlotAxis& X2Axis() { return x2_axis_; }
  const XYPlotAxis& X2Axis() const { return x2_axis_; }

  XYPlotAxis& Y2Axis() { return y2_axis_; }
  const XYPlotAxis& Y2Axis() const { return y2_axis_; }

 protected:
  void Draw(const Cairo::RefPtr<Cairo::Context>& cairo) override;

 private:
  void InitializeComponents(const Cairo::RefPtr<Cairo::Context>& cr);
  void InitializeYAxis(bool second_axis, double horizontal_scale_height);
  void DrawFrame(const Cairo::RefPtr<Cairo::Context>& cr);
  void DrawPointSet(const Cairo::RefPtr<Cairo::Context>& cr,
                    XYPointSet& pointSet);

  static std::pair<double, double> CheckRange(
      const std::pair<double, double>& range) {
    if (!std::isfinite(range.first) || !std::isfinite(range.second)) {
      return {-1.0, 1.0};
    } else if (range.first == range.second) {
      return {range.first - 1.0, range.second + 1.0};
    } else {
      return range;
    }
  }

  // TODO
  Rectangle getPlotArea(size_t width, size_t height) const override {
    return Rectangle();
  }

  const XYPointSet* GetFirstXAxisSet(bool second_axis) const {
    for (const std::unique_ptr<XYPointSet>& set : _pointSets) {
      if (set->UseSecondXAxis() == second_axis) {
        return set.get();
      }
    }
    return nullptr;
  }

  const XYPointSet* GetFirstYAxisSet(bool second_axis) const {
    for (const std::unique_ptr<XYPointSet>& set : _pointSets) {
      if (set->UseSecondYAxis() == second_axis) {
        return set.get();
      }
    }
    return nullptr;
  }

  double _topMargin = 0;
  bool _showAxisDescriptions = true;
  std::vector<std::unique_ptr<XYPointSet>> _pointSets;
  XYPlotAxis x_axis_;
  XYPlotAxis x2_axis_;
  XYPlotAxis y_axis_;
  XYPlotAxis y2_axis_;
  Legend _legend;
  System _system;
  Title _title;
};

#endif