toolbox_FFT.cpp
Go to the documentation of this file.
1 #include "toolbox_FFT.h"
2 #include "ui_toolbox_FFT.h"
3 
4 #include <QDialogButtonBox>
5 #include <QEvent>
6 #include <QMimeData>
7 #include <QDebug>
8 #include <QDragEnterEvent>
9 #include <QSettings>
10 
12 #include "PlotJuggler/svg_util.h"
13 #include "KissFFT/kiss_fftr.h"
14 
16 {
17  _widget = new QWidget(nullptr);
18  ui = new Ui::toolbox_fft;
19 
20  ui->setupUi(_widget);
21 
22  connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &ToolboxPlugin::closed);
23 
24  connect(ui->pushButtonCalculate, &QPushButton::clicked, this,
26 
27  connect(ui->pushButtonSave, &QPushButton::clicked, this, &ToolboxFFT::onSaveCurve);
28 
29  connect(ui->pushButtonClear, &QPushButton::clicked, this, &ToolboxFFT::onClearCurves);
30 }
31 
33 {
34  delete ui;
35 }
36 
37 void ToolboxFFT::init(PJ::PlotDataMapRef& src_data, PJ::TransformsMap& transform_map)
38 {
39  _plot_data = &src_data;
40  _transforms = &transform_map;
41 
42  _plot_widget_A = new PJ::PlotWidgetBase(ui->framePlotPreviewA);
43  _plot_widget_B = new PJ::PlotWidgetBase(ui->framePlotPreviewB);
44 
45  auto preview_layout_A = new QHBoxLayout(ui->framePlotPreviewA);
46  preview_layout_A->setMargin(6);
47  preview_layout_A->addWidget(_plot_widget_A);
48 
49  auto preview_layout_B = new QHBoxLayout(ui->framePlotPreviewB);
50  preview_layout_B->setMargin(6);
51  preview_layout_B->addWidget(_plot_widget_B);
52 
54 
55  connect(_plot_widget_A, &PlotWidgetBase::dragEnterSignal, this,
57 
58  connect(_plot_widget_A, &PlotWidgetBase::dropSignal, this, &ToolboxFFT::onDropEvent);
59 
60  connect(_plot_widget_A, &PlotWidgetBase::viewResized, this, &ToolboxFFT::onViewResized);
61 }
62 
63 std::pair<QWidget*, PJ::ToolboxPlugin::WidgetType> ToolboxFFT::providedWidget() const
64 {
66 }
67 
69 {
70  QSettings settings;
71  QString theme = settings.value("StyleSheet::theme", "light").toString();
72 
73  ui->pushButtonClear->setIcon(LoadSvg(":/resources/svg/clear.svg", theme));
74  return true;
75 }
76 
78 {
80 
81  for (const auto& curve_id : _curve_names)
82  {
83  auto it = _plot_data->numeric.find(curve_id);
84  if (it == _plot_data->numeric.end())
85  {
86  return;
87  }
88  PlotData& curve_data = it->second;
89 
90  if (curve_data.size() == 0)
91  {
92  return;
93  }
94 
95  size_t min_index = 0;
96  size_t max_index = curve_data.size() - 1;
97 
98  if (ui->radioZoomed->isChecked())
99  {
100  min_index = curve_data.getIndexFromX(_zoom_range.min);
101  max_index = curve_data.getIndexFromX(_zoom_range.max);
102  }
103 
104  size_t N = 1 + max_index - min_index;
105 
106  if (N & 1)
107  { // if not even, make it even
108  N--;
109  max_index--;
110  }
111 
112  if (N < 8)
113  {
114  return;
115  }
116 
117  double dT = (curve_data.at(max_index).x - curve_data.at(min_index).x) / double(N - 1);
118 
119  std::vector<kiss_fft_scalar> input;
120  input.reserve(curve_data.size());
121 
122  double sum = 0;
123  if (ui->checkAverage->isChecked())
124  {
125  for (size_t i = 0; i < N; i++)
126  {
127  sum += curve_data[i + min_index].y;
128  }
129  }
130  double average = sum / double(N);
131 
132  for (size_t i = 0; i < N; i++)
133  {
134  size_t index = i + min_index;
135  const auto& p = curve_data[index];
136  input.push_back(static_cast<kiss_fft_scalar>(p.y - average));
137 
138  if (i != 0)
139  {
140  double dTi = (p.x - curve_data[index - 1].x);
141  double diff = dTi - dT;
142  // std_dev += diff*diff;
143  }
144  }
145  // std_dev = sqrt(std_dev / double(N-1) );
146 
147  std::vector<kiss_fft_cpx> out(N / 2 + 1);
148 
149  auto config = kiss_fftr_alloc(N, false, nullptr, nullptr);
150 
151  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
152  kiss_fftr(config, input.data(), out.data());
153  QApplication::restoreOverrideCursor();
154 
155  auto& curver_fft = _local_data.getOrCreateScatterXY(curve_id);
156  curver_fft.clear();
157  for (size_t i = 0; i < N / 2; i++)
158  {
159  kiss_fft_scalar Hz = i * (1.0 / dT) / double(N);
160  kiss_fft_scalar amplitude = std::hypot(out[i].r, out[i].i) / N;
161  curver_fft.pushBack({ Hz, amplitude });
162  }
163 
164  QColor color = Qt::transparent;
165  auto colorHint = curve_data.attribute(COLOR_HINT);
166  if (colorHint.isValid())
167  {
168  color = colorHint.value<QColor>();
169  }
170 
171  _plot_widget_B->addCurve(curve_id + "_FFT", curver_fft, color);
172 
173  free(config);
174  }
175 
177 }
178 
180 {
183 
186 
187  ui->pushButtonSave->setEnabled(false);
188  ui->pushButtonCalculate->setEnabled(false);
189 
190  ui->lineEditSuffix->setEnabled(false);
191  ui->lineEditSuffix->setText("_FFT");
192 
193  _curve_names.clear();
194 }
195 
196 void ToolboxFFT::onDragEnterEvent(QDragEnterEvent* event)
197 {
198  const QMimeData* mimeData = event->mimeData();
199  QStringList mimeFormats = mimeData->formats();
200 
201  for (const QString& format : mimeFormats)
202  {
203  QByteArray encoded = mimeData->data(format);
204  QDataStream stream(&encoded, QIODevice::ReadOnly);
205 
206  if (format != "curveslist/add_curve")
207  {
208  return;
209  }
210 
211  QStringList curves;
212  while (!stream.atEnd())
213  {
214  QString curve_name;
215  stream >> curve_name;
216  if (!curve_name.isEmpty())
217  {
218  curves.push_back(curve_name);
219  }
220  }
221  _dragging_curves = curves;
222  event->accept();
223  }
224 }
225 
226 void ToolboxFFT::onDropEvent(QDropEvent*)
227 {
228  _zoom_range.min = std::numeric_limits<double>::lowest();
229  _zoom_range.max = std::numeric_limits<double>::max();
230 
231  for (auto& curve : _dragging_curves)
232  {
233  std::string curve_id = curve.toStdString();
234  PlotData& curve_data = _plot_data->getOrCreateNumeric(curve_id);
235 
236  _plot_widget_A->addCurve(curve_id, curve_data);
237  _curve_names.push_back(curve_id);
238  _zoom_range.min = std::min(_zoom_range.min, curve_data.front().x);
239  _zoom_range.max = std::max(_zoom_range.max, curve_data.back().x);
240  }
241 
242  ui->pushButtonSave->setEnabled(true);
243  ui->pushButtonCalculate->setEnabled(true);
244  ui->lineEditSuffix->setEnabled(true);
245 
246  _dragging_curves.clear();
248 }
249 
250 void ToolboxFFT::onViewResized(const QRectF& rect)
251 {
252  _zoom_range.min = rect.left();
253  _zoom_range.max = rect.right();
254 }
255 
257 {
258  auto suffix = ui->lineEditSuffix->text().toStdString();
259  if (suffix.empty())
260  {
261  ui->lineEditSuffix->setText("_FFT");
262  suffix = "_FFT";
263  }
264  for (const auto& curve_id : _curve_names)
265  {
266  auto it = _local_data.scatter_xy.find(curve_id);
267  if (it == _local_data.scatter_xy.end())
268  {
269  continue;
270  }
271  auto& out_data = _plot_data->getOrCreateScatterXY(curve_id + suffix);
272  out_data.clonePoints(it->second);
273 
274  // TODO out_data.setAttribute(PJ::DISABLE_LINKED_ZOOM, true);
275  emit plotCreated(curve_id + suffix);
276  }
277 
278  emit closed();
279 }
color
color
Definition: color.h:16
PJ::TimeseriesBase
Definition: timeseries.h:16
ToolboxFFT::~ToolboxFFT
~ToolboxFFT() override
Definition: toolbox_FFT.cpp:32
kiss_fftr.h
ToolboxFFT::_widget
QWidget * _widget
Definition: toolbox_FFT.h:38
ToolboxFFT::onSaveCurve
void onSaveCurve()
Definition: toolbox_FFT.cpp:256
LoadSvg
const QPixmap & LoadSvg(QString filename, QString style_name="light")
Definition: svg_util.h:26
ToolboxFFT::_plot_widget_B
PJ::PlotWidgetBase * _plot_widget_B
Definition: toolbox_FFT.h:46
PJ::PlotWidgetBase::setAcceptDrops
void setAcceptDrops(bool accept)
Definition: plotwidget_base.cpp:522
ToolboxFFT::_local_data
PJ::PlotDataMapRef _local_data
Definition: toolbox_FFT.h:51
PJ::ToolboxPlugin::plotCreated
void plotCreated(std::string plot_name, bool is_custom=true)
ToolboxFFT::providedWidget
std::pair< QWidget *, WidgetType > providedWidget() const override
Definition: toolbox_FFT.cpp:63
PJ::PlotDataBase::clonePoints
void clonePoints(const PlotDataBase &other)
Definition: plotdatabase.h:157
ToolboxFFT::_plot_widget_A
PJ::PlotWidgetBase * _plot_widget_A
Definition: toolbox_FFT.h:45
PJ::PlotWidgetBase::removeAllCurves
virtual void removeAllCurves()
Definition: plotwidget_base.cpp:789
PJ::PlotWidgetBase::resetZoom
virtual void resetZoom()
Definition: plotwidget_base.cpp:175
PJ::TransformsMap
std::unordered_map< std::string, std::shared_ptr< TransformFunction > > TransformsMap
Definition: transform_function.h:85
PJ::COLOR_HINT
@ COLOR_HINT
Definition: plotdatabase.h:55
ToolboxFFT::_curve_names
std::vector< std::string > _curve_names
Definition: toolbox_FFT.h:55
PJ::ToolboxPlugin::FIXED
@ FIXED
Definition: toolbox_base.h:34
PJ::PlotDataBase::clear
virtual void clear()
Definition: plotdatabase.h:213
ToolboxFFT::calculateCurveFFT
void calculateCurveFFT()
Definition: toolbox_FFT.cpp:77
PJ::PlotDataMapRef::numeric
TimeseriesMap numeric
Numerical timeseries.
Definition: plotdata.h:39
PJ::PlotDataBase::back
const Point & back() const
Definition: plotdatabase.h:250
transform_function.h
kiss_fft_scalar
#define kiss_fft_scalar
Definition: kiss_fft.h:82
PJ::PlotWidgetBase::addCurve
virtual CurveInfo * addCurve(const std::string &name, PlotDataXY &src_data, QColor color=Qt::transparent)
Definition: plotwidget_base.cpp:391
ToolboxFFT::init
void init(PJ::PlotDataMapRef &src_data, PJ::TransformsMap &transform_map) override
Definition: toolbox_FFT.cpp:37
ToolboxFFT::onClearCurves
void onClearCurves()
Definition: toolbox_FFT.cpp:179
PJ::Range::max
double max
Definition: plotdatabase.h:27
ToolboxFFT::_zoom_range
Range _zoom_range
Definition: toolbox_FFT.h:53
PJ::PlotDataMapRef::getOrCreateScatterXY
PlotDataXY & getOrCreateScatterXY(const std::string &name, PlotGroup::Ptr group={})
Definition: plotdata.cpp:69
PJ::PlotDataMapRef::scatter_xy
ScatterXYMap scatter_xy
Definition: plotdata.h:36
ToolboxFFT::ToolboxFFT
ToolboxFFT()
Definition: toolbox_FFT.cpp:15
ToolboxFFT::onShowWidget
bool onShowWidget() override
Definition: toolbox_FFT.cpp:68
ToolboxFFT::_transforms
PJ::TransformsMap * _transforms
Definition: toolbox_FFT.h:49
PJ::PlotDataMapRef::getOrCreateNumeric
PlotData & getOrCreateNumeric(const std::string &name, PlotGroup::Ptr group={})
Definition: plotdata.cpp:75
format
auto format(const text_style &ts, const S &format_str, const Args &... args) -> std::basic_string< Char >
Definition: color.h:543
PJ::TimeseriesBase::getIndexFromX
int getIndexFromX(double x) const
Definition: timeseries.h:106
ToolboxFFT::onViewResized
void onViewResized(const QRectF &rect)
Definition: toolbox_FFT.cpp:250
PJ::PlotDataBase::size
virtual size_t size() const
Definition: plotdatabase.h:183
ToolboxFFT::_plot_data
PJ::PlotDataMapRef * _plot_data
Definition: toolbox_FFT.h:48
ToolboxFFT::onDropEvent
void onDropEvent(QDropEvent *event)
Definition: toolbox_FFT.cpp:226
ToolboxFFT::ui
Ui::toolbox_fft * ui
Definition: toolbox_FFT.h:39
ToolboxFFT::onDragEnterEvent
void onDragEnterEvent(QDragEnterEvent *event)
Definition: toolbox_FFT.cpp:196
PJ::PlotDataBase::at
const Point & at(size_t index) const
Definition: plotdatabase.h:193
ToolboxFFT::_dragging_curves
QStringList _dragging_curves
Definition: toolbox_FFT.h:43
PJ::PlotDataBase::attribute
QVariant attribute(PlotAttribute id) const
Definition: plotdatabase.h:239
PJ::PlotDataMapRef
Definition: plotdata.h:34
PJ::PlotDataBase::front
const Point & front() const
Definition: plotdatabase.h:245
PJ::ToolboxPlugin::closed
void closed()
kiss_fftr
void kiss_fftr(kiss_fftr_cfg st, const kiss_fft_scalar *timedata, kiss_fft_cpx *freqdata)
Definition: kiss_fftr.c:63
toolbox_FFT.h
kiss_fftr_alloc
kiss_fftr_cfg kiss_fftr_alloc(int nfft, int inverse_fft, void *mem, size_t *lenmem)
Definition: kiss_fftr.c:21
PJ::Range::min
double min
Definition: plotdatabase.h:26
PJ::PlotWidgetBase
Definition: plotwidget_base.h:25
svg_util.h


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Aug 11 2024 02:24:26