Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
ChartActor.cpp
Go to the documentation of this file.
1/* This file is part of MODEL, the Mechanics Of Defect Evolution Library.
2 *
3 * Copyright (C) 2011 by Giacomo Po <gpo@ucla.edu>.
4 *
5 * model is distributed without any warranty under the
6 * GNU General Public License (GPL) v2 <http://www.gnu.org/licenses/>.
7 */
8
9#ifndef model_ChartActor_cpp_
10#define model_ChartActor_cpp_
11
12#include <fstream>
13#include <string>
14#include <vector>
15
16#include <vtkTable.h>
17#include <vtkFloatArray.h>
18#include <vtkPlot.h>
19#include <vtkPoints.h>
20#include <vtkAxis.h>
21
22#include <ChartActor.h>
23#include <vtkTextProperty.h>
24
25#include <DDqtControls.h>
26#include <cmath>
27
28namespace model
29{
30
31 ChartActor::ChartActor(const DefectiveCrystalTraitsIO& traitsIO_in,vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow_in,vtkRenderer* const renderer_in) :
32 /* init */ traitsIO(traitsIO_in)
33 /* init */,mainLayout(new QGridLayout(this))
34 /* init */,showChart(new QCheckBox(this))
35 /* init */,chartUpdate(new QPushButton("Reload",this))
36 /* init */,xComboBox(new QComboBox(this))
37 /* init */,yComboBox(new QComboBox(this))
38 /* init */,xAxisLog(new QCheckBox(this))
39 /* init */,yAxisLog(new QCheckBox(this))
40 /* init */,customScaleBoxX(new controls::GroupBox(tr("&Custom scale X")))
41 /* init */,minScaleX(new QLineEdit(tr("0")))
42 /* init */,maxScaleX(new QLineEdit(tr("1")))
43 /* init */,customScaleBoxY(new controls::GroupBox(tr("&Custom scale Y")))
44 /* init */,minScaleY(new QLineEdit(tr("0")))
45 /* init */,maxScaleY(new QLineEdit(tr("1")))
46 /* init */,renderWindow(renderWindow_in)
47 /* init */,renderer(renderer_in)
48 /* init */,chart(vtkSmartPointer<vtkChartXY>::New())
49 /* init */,chartScene(vtkSmartPointer<vtkContextScene>::New())
50 /* init */,chartActor(vtkSmartPointer<vtkContextActor>::New())
51 /* init */,table(vtkSmartPointer<vtkTable>::New())
52 /* init */,currentTable(vtkSmartPointer<vtkTable>::New())
53 /* init */,colors(vtkSmartPointer<vtkNamedColors>::New())
54 /* init */,points(chart->AddPlot(vtkChart::LINE))
55 /* init */,currentPoints(chart->AddPlot(vtkChart::LINE))
56 {
57
58 showChart->setChecked(false);
59 showChart->setText("chart");
60 chartUpdate->setEnabled(false);
61 xComboBox->setEnabled(false);
62 yComboBox->setEnabled(false);
63 chartActor->SetVisibility(false);
64
65 xAxisLog->setChecked(false);
66 xAxisLog->setEnabled(false);
67 xAxisLog->setText("log-scale");
68
69 yAxisLog->setChecked(false);
70 yAxisLog->setEnabled(false);
71 yAxisLog->setText("log-scale");
72
73 vtkColor3d color3d1 = colors->GetColor3d("black");
74 points->SetColorF(color3d1.GetRed(), color3d1.GetGreen(), color3d1.GetBlue());
75 points->SetWidth(5.0);
76
77 vtkColor3d color3d2 = colors->GetColor3d("magenta");
78 currentPoints->SetColorF(color3d2.GetRed(), color3d2.GetGreen(), color3d2.GetBlue());
79 currentPoints->SetWidth(5.0);
80
81 std::ifstream flabFile(traitsIO.flabFile);
82 if(flabFile)
83 {
84 std::cout<<"Reading "<<traitsIO.flabFile<<" ... "<<std::flush;
85 const auto t0= std::chrono::system_clock::now();
86
87 std::string line;
88 while (std::getline(flabFile, line))
89 {
90 if(!line.empty())
91 {
92// std::cout<<line<<std::endl;
93 xComboBox->addItem(QString::fromStdString(line));
94 yComboBox->addItem(QString::fromStdString(line));
95
96// vtkNew<vtkFloatArray> farr;
97// farr->SetName(line.c_str());
98// table->AddColumn(farr);
99 }
100 }
101 std::cout<<magentaColor<<" ["<<(std::chrono::duration<double>(std::chrono::system_clock::now()-t0)).count()<<" sec]"<<defaultColor<<std::endl;
102 }
103 else
104 {
105 std::cout<<"Unable to read "<<traitsIO.flabFile<<std::endl;
106 }
107
108 QGridLayout* autoscaleLayoutX = new QGridLayout();
109 customScaleBoxX->setToolTip("Override automatic X-axis bounds with the entered limits.");
110 customScaleBoxX->setCheckable(true);
111// customScaleBoxX->setEnabled(false);
112 customScaleBoxX->setChecked(false);
113 controls::field(autoscaleLayoutX, 0, "Minimum", minScaleX,
114 "X-axis bound used when custom scaling is enabled. Press Enter to apply.");
115
116 controls::field(autoscaleLayoutX, 1, "Maximum", maxScaleX,
117 "X-axis bound used when custom scaling is enabled. Press Enter to apply.");
118
119 customScaleBoxX->setLayout(autoscaleLayoutX);
120
121 QGridLayout* autoscaleLayoutY = new QGridLayout();
122 customScaleBoxY->setToolTip("Override automatic Y-axis bounds with the entered limits.");
123 customScaleBoxY->setCheckable(true);
124// customScaleBoxY->setEnabled(false);
125 customScaleBoxY->setChecked(false);
126 controls::field(autoscaleLayoutY, 0, "Minimum", minScaleY,
127 "Y-axis bound used when custom scaling is enabled. Press Enter to apply.");
128
129 controls::field(autoscaleLayoutY, 1, "Maximum", maxScaleY,
130 "Y-axis bound used when custom scaling is enabled. Press Enter to apply.");
131
132 customScaleBoxY->setLayout(autoscaleLayoutY);
133
134 auto *chartBox = controls::box("Chart", this, "Show or hide the simulation-history chart.", showChart);
135 auto *chartLayout = controls::grid(chartBox);
136 chartLayout->addWidget(chartUpdate, 0, 0, 1, 2);
137 chartUpdate->setToolTip("Reload the simulation history file and refresh the chart.");
138 auto *xBox =
139 controls::box("X axis", this, "Select the plotted quantity, axis scaling and optional bounds.");
140 controls::field(controls::grid(xBox), 0, "Quantity", xComboBox,
141 "Simulation-history column to plot on this axis.");
142 controls::grid(xBox)->addWidget(xAxisLog, 1, 0, 1, 2);
143 xAxisLog->setToolTip("Use a logarithmic axis. Displayed values must be positive.");
144 controls::grid(xBox)->addWidget(customScaleBoxX, 2, 0, 1, 2);
145 chartLayout->addWidget(xBox, 1, 0, 1, 2);
146 auto *yBox =
147 controls::box("Y axis", this, "Select the plotted quantity, axis scaling and optional bounds.");
148 controls::field(controls::grid(yBox), 0, "Quantity", yComboBox,
149 "Simulation-history column to plot on this axis.");
150 controls::grid(yBox)->addWidget(yAxisLog, 1, 0, 1, 2);
151 yAxisLog->setToolTip("Use a logarithmic axis. Displayed values must be positive.");
152 controls::grid(yBox)->addWidget(customScaleBoxY, 2, 0, 1, 2);
153 chartLayout->addWidget(yBox, 2, 0, 1, 2);
154 mainLayout->addWidget(chartBox, 0, 0);
155 mainLayout->setRowStretch(1, 1);
156 this->setLayout(mainLayout);
157
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})
167 {
168 connect(edit, &QLineEdit::returnPressed, this, &ChartActor::modify);
169 }
170
171 chartScene->AddItem(chart);
172 chartActor->SetScene(chartScene);
173 renderer->AddActor(chartActor);
174 chartScene->SetRenderer(renderer);
175
176 }
177
178 void ChartActor::reload()
179 {
180 table->Initialize();
181
182 const int cols(xComboBox->count());
183
184 for(int c=0;c<cols;++c)
185 {
186 vtkNew<vtkFloatArray> farr;
187 farr->SetName(xComboBox->itemText(c).toStdString().c_str());
188 table->AddColumn(farr);
189 }
190
191
192 std::ifstream fFile(traitsIO.fFile);
193 if(fFile)
194 {
195 std::cout<<"Reading "<<traitsIO.fFile<<" ... "<<std::flush;
196 const auto t0= std::chrono::system_clock::now();
197 double temp(0.0);
198 std::string line;
199 while (std::getline(fFile, line))
200 {
201 if(!line.empty())
202 {
203 const auto row=table->InsertNextBlankRow(cols);
204 std::stringstream ss(line);
205 for(int col=0;col<cols;++col)
206 {
207 ss >> temp;
208 table->SetValue(row, col, temp);
209 }
210 }
211 }
212 std::cout<<magentaColor<<" ["<<(std::chrono::duration<double>(std::chrono::system_clock::now()-t0)).count()<<" sec]"<<defaultColor<<std::endl;
213 }
214 else
215 {
216 std::cout<<"Unable to read "<<traitsIO.fFile<<std::endl;
217 }
218
219 table->Modified();
220 updatePlots();
221 }
222
223 void ChartActor::updateConfiguration(const size_t& frameID)
224 {
225
226 if(frameID==0)
227 {
228 reload();
229 }
230
231 std::cout<<"Updating chart..."<<std::flush;
232 const auto t0= std::chrono::system_clock::now();
233
234
235 currentTable->Initialize();
236
237 for(long long k=0;k<table->GetNumberOfColumns();++k)
238 {
239 vtkNew<vtkFloatArray> farr;
240 farr->SetName(table->GetColumnName(k));
241 currentTable->AddColumn(farr);
242 }
243
244 for(long long k=0;k<table->GetNumberOfRows();++k)
245 {
246 if(table->GetValue(k,0)<=frameID)
247 {
248 const auto row=currentTable->InsertNextBlankRow(table->GetNumberOfColumns());
249 for(int col=0;col<table->GetNumberOfColumns();++col)
250 {
251 currentTable->SetValue(row, col, table->GetValue(row,col));
252 }
253 }
254 }
255 currentTable->Modified();
256 updatePlots();
257 std::cout<<magentaColor<<" ["<<(std::chrono::duration<double>(std::chrono::system_clock::now()-t0)).count()<<" sec]"<<defaultColor<<std::endl;
258
259 }
260
261void ChartActor::updatePlots()
262{
263 if(xComboBox->count() && yComboBox->count())
264 {
265 if( table->GetNumberOfColumns()>xComboBox->currentIndex()
266 && table->GetNumberOfColumns()>yComboBox->currentIndex())
267 {
268 points->SetInputData(table, xComboBox->currentIndex(), yComboBox->currentIndex());
269 }
270
271 if( currentTable->GetNumberOfColumns()>xComboBox->currentIndex()
272 && currentTable->GetNumberOfColumns()>yComboBox->currentIndex())
273 {
274 currentPoints->SetInputData(currentTable, xComboBox->currentIndex(), yComboBox->currentIndex());
275 }
276
277 const auto applyRange = [](vtkAxis *axis, QGroupBox *group, QLineEdit *minimum, QLineEdit *maximum)
278 {
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})
287 {
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.");
291 }
292 axis->SetBehavior(group->isChecked() && valid ? vtkAxis::FIXED : vtkAxis::AUTO);
293 if(group->isChecked() && valid)
294 {
295 axis->SetUnscaledRange(lower, upper);
296 }
297 };
298 applyRange(chart->GetAxis(1), customScaleBoxX, minScaleX, maxScaleX);
299 applyRange(chart->GetAxis(0), customScaleBoxY, minScaleY, maxScaleY);
300 chart->RecalculateBounds();
301 chart->Modified();
302
303 }
304}
305
306
307
308 void ChartActor::modify()
309 {
310// std::cout<<"modifying chart..."<<std::endl;
311
312 xComboBox->setEnabled(showChart->isChecked());
313 yComboBox->setEnabled(showChart->isChecked());
314 customScaleBoxX->setEnabled(showChart->isChecked());
315 customScaleBoxY->setEnabled(showChart->isChecked());
316
317 xAxisLog->setEnabled(showChart->isChecked());
318 yAxisLog->setEnabled(showChart->isChecked());
319 chartUpdate->setEnabled(showChart->isChecked());
320
321
322 chart->GetAxis(0)->SetTitle(yComboBox->currentText().toStdString());
323 chart->GetAxis(1)->SetTitle(xComboBox->currentText().toStdString());
324
325 chart->GetAxis(0)->SetLogScale(yAxisLog->isChecked());
326 chart->GetAxis(1)->SetLogScale(xAxisLog->isChecked());
327
328 chart->GetAxis(0)->SetGridVisible(false);
329 chart->GetAxis(1)->SetGridVisible(false);
330
331 chart->GetAxis(0)->SetNumberOfTicks(10);
332 chart->GetAxis(1)->SetNumberOfTicks(10);
333
334 chart->GetAxis(0)->GetLabelProperties()->SetFontSize(16);
335 chart->GetAxis(1)->GetLabelProperties()->SetFontSize(16);
336
337 chart->GetAxis(0)->GetTitleProperties()->SetFontSize(16);
338 chart->GetAxis(1)->GetTitleProperties()->SetFontSize(16);
339
340
341 updatePlots();
342
343
344// std::cout<<"xComboBox->currentIndex()="<<xComboBox->currentIndex()<<std::endl;
345// std::cout<<"yComboBox->currentIndex()="<<yComboBox->currentIndex()<<std::endl;
346// std::cout<<"table->GetNumberOfRows()="<<table->GetNumberOfRows()<<std::endl;
347// std::cout<<"table->GetNumberOfColumns()="<<table->GetNumberOfColumns()<<std::endl;
348// std::cout<<"currentTable->GetNumberOfRows()="<<currentTable->GetNumberOfRows()<<std::endl;
349// std::cout<<"currentTable->GetNumberOfColumns()="<<currentTable->GetNumberOfColumns()<<std::endl;
350
351
352// chart->ClearPlots();
353
354// if(xComboBox->count() && yComboBox->count())
355// {
356// if( table->GetNumberOfColumns()>xComboBox->currentIndex()
357// && table->GetNumberOfColumns()>yComboBox->currentIndex()
359// )
360// {
362// points->SetInputData(table, xComboBox->currentIndex(), yComboBox->currentIndex());
366// }
367//
368// if( currentTable->GetNumberOfColumns()>xComboBox->currentIndex()
369// && currentTable->GetNumberOfColumns()>yComboBox->currentIndex()
371// )
372// {
374// currentPoints->SetInputData(currentTable, xComboBox->currentIndex(), yComboBox->currentIndex());
378// }
379//
380// chart->RecalculateBounds();
381// chart->Modified();
382//
383// }
384
385 chartActor->SetVisibility(showChart->isChecked());
386 renderWindow->Render(); // this makes code crash if called before the app window is created
387
388// std::cout<<"Min/Max="<<chart->GetAxis(0)->GetMinimum()<<", "<<chart->GetAxis(0)->GetMaximum()<<std::endl;
389
390 }
391
392
393
394} // namespace model
395#endif
396
397
398
399
400
401
402
c
Definition int_R.m:15
line(ax, points, color=BLUE, dashed=False, z=4)
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
Definition ChartActor.h:89
QCheckBox * xAxisLog
Definition ChartActor.h:71
QComboBox * xComboBox
Definition ChartActor.h:69
vtkSmartPointer< vtkNamedColors > colors
Definition ChartActor.h:90
QCheckBox * showChart
Definition ChartActor.h:67
vtkSmartPointer< vtkGenericOpenGLRenderWindow > renderWindow
Definition ChartActor.h:81
QCheckBox * yAxisLog
Definition ChartActor.h:72
QGridLayout * mainLayout
Definition ChartActor.h:66
QLineEdit * maxScaleX
Definition ChartActor.h:75
vtkPlot * currentPoints
Definition ChartActor.h:93
vtkRenderer *const renderer
Definition ChartActor.h:82
const DefectiveCrystalTraitsIO & traitsIO
Definition ChartActor.h:65
vtkSmartPointer< vtkContextActor > chartActor
Definition ChartActor.h:86
vtkSmartPointer< vtkTable > table
Definition ChartActor.h:88
QGroupBox * customScaleBoxX
Definition ChartActor.h:73
QLineEdit * maxScaleY
Definition ChartActor.h:78
QLineEdit * minScaleX
Definition ChartActor.h:74
vtkPlot * points
Definition ChartActor.h:92
QGroupBox * customScaleBoxY
Definition ChartActor.h:76
QPushButton * chartUpdate
Definition ChartActor.h:68
void updateConfiguration(const size_t &frameID)
vtkSmartPointer< vtkContextScene > chartScene
Definition ChartActor.h:85
QComboBox * yComboBox
Definition ChartActor.h:70
QLineEdit * minScaleY
Definition ChartActor.h:77
vtkSmartPointer< vtkChartXY > chart
Definition ChartActor.h:84
ChartActor(const DefectiveCrystalTraitsIO &traitsIO_in, vtkSmartPointer< vtkGenericOpenGLRenderWindow >, vtkRenderer *const renderer_in)
REAL t0
newsubseg ss[0]
int axis
int k
vertex temp