9#ifndef model_ChartActor_cpp_
10#define model_ChartActor_cpp_
17#include <vtkFloatArray.h>
23#include <vtkTextProperty.h>
48 ,
chart(vtkSmartPointer<vtkChartXY>::New())
49 ,
chartScene(vtkSmartPointer<vtkContextScene>::New())
50 ,
chartActor(vtkSmartPointer<vtkContextActor>::New())
51 ,
table(vtkSmartPointer<vtkTable>::New())
53 ,
colors(vtkSmartPointer<vtkNamedColors>::New())
73 vtkColor3d color3d1 =
colors->GetColor3d(
"black");
74 points->SetColorF(color3d1.GetRed(), color3d1.GetGreen(), color3d1.GetBlue());
77 vtkColor3d color3d2 =
colors->GetColor3d(
"magenta");
78 currentPoints->SetColorF(color3d2.GetRed(), color3d2.GetGreen(), color3d2.GetBlue());
81 std::ifstream flabFile(
traitsIO.flabFile);
84 std::cout<<
"Reading "<<traitsIO.flabFile<<
" ... "<<std::flush;
85 const auto t0= std::chrono::system_clock::now();
88 while (std::getline(flabFile, line))
93 xComboBox->addItem(QString::fromStdString(line));
94 yComboBox->addItem(QString::fromStdString(line));
101 std::cout<<
magentaColor<<
" ["<<(std::chrono::duration<double>(std::chrono::system_clock::now()-
t0)).count()<<
" sec]"<<
defaultColor<<std::endl;
105 std::cout<<
"Unable to read "<<traitsIO.flabFile<<std::endl;
108 QGridLayout* autoscaleLayoutX =
new QGridLayout();
109 customScaleBoxX->setToolTip(
"Override automatic X-axis bounds with the entered limits.");
110 customScaleBoxX->setCheckable(
true);
112 customScaleBoxX->setChecked(
false);
114 "X-axis bound used when custom scaling is enabled. Press Enter to apply.");
117 "X-axis bound used when custom scaling is enabled. Press Enter to apply.");
119 customScaleBoxX->setLayout(autoscaleLayoutX);
121 QGridLayout* autoscaleLayoutY =
new QGridLayout();
122 customScaleBoxY->setToolTip(
"Override automatic Y-axis bounds with the entered limits.");
123 customScaleBoxY->setCheckable(
true);
125 customScaleBoxY->setChecked(
false);
127 "Y-axis bound used when custom scaling is enabled. Press Enter to apply.");
130 "Y-axis bound used when custom scaling is enabled. Press Enter to apply.");
132 customScaleBoxY->setLayout(autoscaleLayoutY);
134 auto *chartBox =
controls::box(
"Chart",
this,
"Show or hide the simulation-history chart.", showChart);
136 chartLayout->addWidget(chartUpdate, 0, 0, 1, 2);
137 chartUpdate->setToolTip(
"Reload the simulation history file and refresh the chart.");
139 controls::box(
"X axis",
this,
"Select the plotted quantity, axis scaling and optional bounds.");
141 "Simulation-history column to plot on this axis.");
143 xAxisLog->setToolTip(
"Use a logarithmic axis. Displayed values must be positive.");
145 chartLayout->addWidget(xBox, 1, 0, 1, 2);
147 controls::box(
"Y axis",
this,
"Select the plotted quantity, axis scaling and optional bounds.");
149 "Simulation-history column to plot on this axis.");
151 yAxisLog->setToolTip(
"Use a logarithmic axis. Displayed values must be positive.");
153 chartLayout->addWidget(yBox, 2, 0, 1, 2);
154 mainLayout->addWidget(chartBox, 0, 0);
155 mainLayout->setRowStretch(1, 1);
156 this->setLayout(mainLayout);
158 connect(showChart,SIGNAL(stateChanged(
int)),
this, SLOT(modify()));
159 connect(xAxisLog, SIGNAL(stateChanged(
int)),
this, SLOT(modify()));
160 connect(yAxisLog, SIGNAL(stateChanged(
int)),
this, SLOT(modify()));
161 connect(xComboBox,SIGNAL(currentIndexChanged(
int)),
this, SLOT(modify()));
162 connect(yComboBox,SIGNAL(currentIndexChanged(
int)),
this, SLOT(modify()));
163 connect(chartUpdate,SIGNAL(released()),
this, SLOT(reload()));
164 connect(customScaleBoxX, &QGroupBox::toggled,
this, &ChartActor::modify);
165 connect(customScaleBoxY, &QGroupBox::toggled,
this, &ChartActor::modify);
166 for(
auto *edit : {minScaleX, maxScaleX, minScaleY, maxScaleY})
168 connect(edit, &QLineEdit::returnPressed,
this, &ChartActor::modify);
171 chartScene->AddItem(chart);
172 chartActor->SetScene(chartScene);
173 renderer->AddActor(chartActor);
174 chartScene->SetRenderer(renderer);
178 void ChartActor::reload()
182 const int cols(xComboBox->count());
184 for(
int c=0;
c<cols;++
c)
186 vtkNew<vtkFloatArray> farr;
187 farr->SetName(xComboBox->itemText(
c).toStdString().c_str());
188 table->AddColumn(farr);
192 std::ifstream
fFile(traitsIO.fFile);
195 std::cout<<
"Reading "<<traitsIO.fFile<<
" ... "<<std::flush;
196 const auto t0= std::chrono::system_clock::now();
199 while (std::getline(fFile, line))
203 const auto row=table->InsertNextBlankRow(cols);
204 std::stringstream
ss(line);
205 for(
int col=0;col<cols;++col)
208 table->SetValue(row, col,
temp);
212 std::cout<<magentaColor<<
" ["<<(std::chrono::duration<double>(std::chrono::system_clock::now()-
t0)).
count()<<
" sec]"<<defaultColor<<std::endl;
216 std::cout<<
"Unable to read "<<traitsIO.fFile<<std::endl;
231 std::cout<<
"Updating chart..."<<std::flush;
232 const auto t0= std::chrono::system_clock::now();
237 for(
long long k=0;
k<
table->GetNumberOfColumns();++
k)
239 vtkNew<vtkFloatArray> farr;
240 farr->SetName(
table->GetColumnName(
k));
244 for(
long long k=0;
k<
table->GetNumberOfRows();++
k)
246 if(
table->GetValue(
k,0)<=frameID)
249 for(
int col=0;col<
table->GetNumberOfColumns();++col)
261void ChartActor::updatePlots()
263 if(xComboBox->count() && yComboBox->count())
265 if( table->GetNumberOfColumns()>xComboBox->currentIndex()
266 && table->GetNumberOfColumns()>yComboBox->currentIndex())
268 points->SetInputData(table, xComboBox->currentIndex(), yComboBox->currentIndex());
271 if( currentTable->GetNumberOfColumns()>xComboBox->currentIndex()
272 && currentTable->GetNumberOfColumns()>yComboBox->currentIndex())
274 currentPoints->SetInputData(currentTable, xComboBox->currentIndex(), yComboBox->currentIndex());
277 const auto applyRange = [](vtkAxis *
axis, QGroupBox *group, QLineEdit *minimum, QLineEdit *maximum)
279 bool minimumOK =
false;
280 bool maximumOK =
false;
281 const double lower = minimum->text().toDouble(&minimumOK);
282 const double upper = maximum->text().toDouble(&maximumOK);
283 const bool valid = minimumOK && maximumOK && std::isfinite(lower) && std::isfinite(upper) &&
284 lower < upper && (!
axis->GetLogScale() || lower > 0.0);
285 const bool invalid = group->isChecked() && !valid;
286 for(
auto *edit : {minimum, maximum})
288 edit->setStyleSheet(invalid ?
"QLineEdit { border: 1px solid #c44; }" :
"");
289 edit->setToolTip(
"Enter finite limits with minimum < maximum; logarithmic limits must be positive. "
290 "Press Enter to apply. Invalid limits use automatic scaling.");
292 axis->SetBehavior(group->isChecked() && valid ? vtkAxis::FIXED : vtkAxis::AUTO);
293 if(group->isChecked() && valid)
295 axis->SetUnscaledRange(lower, upper);
298 applyRange(chart->GetAxis(1), customScaleBoxX, minScaleX, maxScaleX);
299 applyRange(chart->GetAxis(0), customScaleBoxY, minScaleY, maxScaleY);
300 chart->RecalculateBounds();
308 void ChartActor::modify()
312 xComboBox->setEnabled(showChart->isChecked());
313 yComboBox->setEnabled(showChart->isChecked());
314 customScaleBoxX->setEnabled(showChart->isChecked());
315 customScaleBoxY->setEnabled(showChart->isChecked());
317 xAxisLog->setEnabled(showChart->isChecked());
318 yAxisLog->setEnabled(showChart->isChecked());
319 chartUpdate->setEnabled(showChart->isChecked());
322 chart->GetAxis(0)->SetTitle(yComboBox->currentText().toStdString());
323 chart->GetAxis(1)->SetTitle(xComboBox->currentText().toStdString());
325 chart->GetAxis(0)->SetLogScale(yAxisLog->isChecked());
326 chart->GetAxis(1)->SetLogScale(xAxisLog->isChecked());
328 chart->GetAxis(0)->SetGridVisible(
false);
329 chart->GetAxis(1)->SetGridVisible(
false);
331 chart->GetAxis(0)->SetNumberOfTicks(10);
332 chart->GetAxis(1)->SetNumberOfTicks(10);
334 chart->GetAxis(0)->GetLabelProperties()->SetFontSize(16);
335 chart->GetAxis(1)->GetLabelProperties()->SetFontSize(16);
337 chart->GetAxis(0)->GetTitleProperties()->SetFontSize(16);
338 chart->GetAxis(1)->GetTitleProperties()->SetFontSize(16);
385 chartActor->SetVisibility(showChart->isChecked());
386 renderWindow->Render();
QGridLayout * grid(QGroupBox *group)
QGroupBox * box(const QString &title, QWidget *parent, const QString &description, QCheckBox *toggle=nullptr)
void field(QGridLayout *layout, int row, const QString &title, QWidget *input, const QString &description)
size_t InstanceCount< Derived >::count
static std::string magentaColor
static std::string defaultColor
vtkSmartPointer< vtkTable > currentTable
vtkSmartPointer< vtkNamedColors > colors
vtkSmartPointer< vtkGenericOpenGLRenderWindow > renderWindow
vtkRenderer *const renderer
const DefectiveCrystalTraitsIO & traitsIO
vtkSmartPointer< vtkContextActor > chartActor
vtkSmartPointer< vtkTable > table
QGroupBox * customScaleBoxX
QGroupBox * customScaleBoxY
QPushButton * chartUpdate
void updateConfiguration(const size_t &frameID)
vtkSmartPointer< vtkContextScene > chartScene
vtkSmartPointer< vtkChartXY > chart
ChartActor(const DefectiveCrystalTraitsIO &traitsIO_in, vtkSmartPointer< vtkGenericOpenGLRenderWindow >, vtkRenderer *const renderer_in)