vtkXYChartRepresentationInternals.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: ParaView
4  Module: vtkXYChartRepresentationInternals.h
5 
6  Copyright (c) Kitware, Inc.
7  All rights reserved.
8  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
9 
10  This software is distributed WITHOUT ANY WARRANTY; without even
11  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  PURPOSE. See the above copyright notice for more information.
13 
14 =========================================================================*/
21 #ifndef vtkXYChartRepresentationInternals_h
22 #define vtkXYChartRepresentationInternals_h
23 
24 #include "vtkCSVExporter.h" // for vtkCSVExporter
25 #include "vtkChartXY.h" // for vtkChartXY
26 #include "vtkDataArray.h" // for vtkDataArray
27 #include "vtkPen.h" // for vtkPen enums
28 #include "vtkPlotBar.h" // for vtkPlotBar
29 #include "vtkPlotFunctionalBag.h" // for vtkPlotFunctionalBag
30 #include "vtkPlotPoints.h" // for vtkPlotPoints
31 #include "vtkSmartPointer.h" // for vtkSmartPointer
32 #include "vtkTable.h" // for vtkTable
33 #include "vtkXYChartRepresentation.h" // for vtkXYChartRepresentation
34 
35 #include <map> // for std::map
36 #include <string> // for std::string
37 
39 {
40 protected:
41  struct TableInfo
42  {
43  std::string TableName;
44  std::string ColumnName;
45  std::string Role;
46  unsigned int Block;
47  };
48 
49  struct PlotInfo
50  {
52  std::string TableName;
53  std::string ColumnName;
54  };
55 
56  typedef std::map<std::string, PlotInfo> PlotsMapItem;
57  class PlotsMap : public std::map<std::string, PlotsMapItem>
58  {
59  bool Contains(const std::string& key, const std::string& role) const
60  {
61  PlotsMap::const_iterator iter1 = this->find(key);
62  if (iter1 != this->end())
63  {
64  PlotsMapItem::const_iterator iter2 = iter1->second.find(role);
65  return (iter2 != iter1->second.end());
66  }
67  return false;
68  }
69 
70  public:
71  vtkSmartPointer<vtkPlot> GetPlot(vtkChartRepresentation* self, const std::string& tableName,
72  const std::string& columnName, const std::string& role = std::string()) const
73  {
74  const std::string key = self->GetDefaultSeriesLabel(tableName, columnName);
75  PlotsMap::const_iterator iter1 = this->find(key);
76  if (iter1 != this->end())
77  {
78  PlotsMapItem::const_iterator iter2 = iter1->second.find(role);
79  if (iter2 != iter1->second.end())
80  {
81  return iter2->second.Plot;
82  }
83  }
84  return vtkSmartPointer<vtkPlot>();
85  }
86 
87  bool RemovePlot(vtkChartRepresentation* self, const std::string& tableName,
88  const std::string& columnName, const std::string& role = std::string())
89  {
90  const std::string key = self->GetDefaultSeriesLabel(tableName, columnName);
91  PlotsMap::iterator iter1 = this->find(key);
92  if (iter1 != this->end())
93  {
94  PlotsMapItem::iterator iter2 = iter1->second.find(role);
95  if (iter2 != iter1->second.end())
96  {
97  iter1->second.erase(iter2);
98  return true;
99  }
100  }
101  return false;
102  }
103 
104  void AddPlot(vtkChartRepresentation* self, const std::string& tableName,
105  const std::string& columnName, const std::string& role, vtkPlot* plot)
106  {
107  const std::string key = self->GetDefaultSeriesLabel(tableName, columnName);
108  PlotInfo& info = (*this)[key][role];
109  info.TableName = tableName;
110  info.ColumnName = columnName;
111  info.Plot = plot;
112  }
113 
114  void SetPlotVisibility(bool val) const
115  {
116  for (PlotsMap::const_iterator iter1 = this->begin(); iter1 != this->end(); ++iter1)
117  {
118  for (PlotsMapItem::const_iterator iter2 = iter1->second.begin();
119  iter2 != iter1->second.end(); ++iter2)
120  {
121  iter2->second.Plot->SetVisible(val);
122  }
123  }
124  }
125 
126  void RemoveAllPlots(vtkChartXY* chartXY)
127  {
128  for (PlotsMap::const_iterator iter1 = this->begin(); iter1 != this->end(); ++iter1)
129  {
130  for (PlotsMapItem::const_iterator iter2 = iter1->second.begin();
131  iter2 != iter1->second.end(); ++iter2)
132  {
133  chartXY->RemovePlotInstance(iter2->second.Plot.GetPointer());
134  }
135  }
136  this->clear();
137  }
138 
139  void Intersect(const PlotsMap& other, vtkChartXY* chartXY)
140  {
141  for (PlotsMap::iterator iter1 = this->begin(); iter1 != this->end(); ++iter1)
142  {
143  for (PlotsMapItem::iterator iter2 = iter1->second.begin(); iter2 != iter1->second.end();)
144  {
145  if (other.Contains(iter1->first, iter2->first) == false)
146  {
147  chartXY->RemovePlotInstance(iter2->second.Plot.GetPointer());
148  PlotsMapItem::iterator iter2old = iter2;
149  ++iter2;
150  iter1->second.erase(iter2old);
151  }
152  else
153  {
154  ++iter2;
155  }
156  }
157  }
158  }
159  };
160 
162 
163  //---------------------------------------------------------------------------
172  template <class T>
173  T GetSeriesParameter(vtkXYChartRepresentation* self, const std::string& tableName,
174  const std::string& columnName, const std::string& vtkNotUsed(role),
175  const std::map<std::string, T>& parameter_map, const T default_value = T()) const
176  {
177  typename std::map<std::string, T>::const_iterator iter;
178 
179  // when setting properties for a series, I want to support two mechanisms:
180  // simply specifying the array name or suffixing it with the block-name.
181  // This logic makes that possible.
182 
183  // first try most specific form of identifying the series.
184  std::string key = self->GetDefaultSeriesLabel(tableName, columnName);
185  iter = parameter_map.find(key);
186  if (iter != parameter_map.end())
187  {
188  return iter->second;
189  }
190 
191  // now try the cheap form for identifying it.
192  key = self->GetDefaultSeriesLabel(std::string(), columnName);
193  iter = parameter_map.find(key);
194  if (iter != parameter_map.end())
195  {
196  return iter->second;
197  }
198  return default_value;
199  }
200 
201 public:
203 
204  // we have to keep these separate since they are set by different properties
205  // and hence may not always match up.
206  std::map<std::string, bool> SeriesVisibilities;
207  std::map<std::string, int> SeriesOrder;
208  std::map<std::string, int> LineThicknesses;
209  std::map<std::string, int> LineStyles;
210  std::map<std::string, vtkColor3d> Colors;
211  std::map<std::string, double> Opacities;
212  std::map<std::string, int> AxisCorners;
213  std::map<std::string, int> MarkerStyles;
214  std::map<std::string, double> MarkerSizes;
215  std::map<std::string, std::string> Labels;
216  std::map<std::string, bool> UseColorMapping;
217  std::map<std::string, vtkScalarsToColors*> Lut;
218 
219  // These are used to determine when to recalculate chart bounds. If user
220  // changes the X axis, we force recalculation of the chart bounds
221  // automatically.
224 
226  : PreviousUseIndexForXAxis(false)
227  {
228  }
229 
230  virtual ~vtkInternals() = default;
231 
232  //---------------------------------------------------------------------------
236  void HideAllPlots() { this->SeriesPlots.SetPlotVisibility(false); }
237 
238  //---------------------------------------------------------------------------
242  void RemoveAllPlots(vtkChartXY* chartXY) { this->SeriesPlots.RemoveAllPlots(chartXY); }
243 
244  //---------------------------------------------------------------------------
250  virtual std::vector<std::string> GetSeriesRoles(
251  const std::string& vtkNotUsed(tableName), const std::string& vtkNotUsed(columnName))
252  {
253  return { std::string() };
254  }
255 
256  //---------------------------------------------------------------------------
260  virtual vtkPlot* NewPlot(vtkXYChartRepresentation* self, const std::string& tableName,
261  const std::string& columnName, const std::string& role, unsigned int block = 0)
262  {
263  (void)tableName;
264  (void)columnName;
265  (void)role;
266 
267  assert(self);
268  vtkChartXY* chartXY = self->GetChart();
269 
270  assert(chartXY);
271  return chartXY->AddPlot(self->GetChartType(), block);
272  }
273 
274  //---------------------------------------------------------------------------
275  virtual int GetInputArrayIndex(const std::string& vtkNotUsed(tableName),
276  const std::string& vtkNotUsed(columnName), const std::string& vtkNotUsed(role))
277  {
278  return 1;
279  }
280 
281  //---------------------------------------------------------------------------
285  virtual void UpdatePlots(vtkXYChartRepresentation* self, const MapOfTables& tables)
286  {
287  PlotsMap newPlots;
288  assert(self != nullptr);
289  vtkChartXY* chartXY = self->GetChart();
290  this->RemoveAllPlots(chartXY);
291  std::multimap<int, std::pair<vtkTable*, TableInfo>> orderMap;
292  for (MapOfTables::const_iterator tablesIter = tables.begin(); tablesIter != tables.end();
293  ++tablesIter)
294  {
295  const std::string& tableName = tablesIter->first;
296  vtkTable* table = tablesIter->second.first.GetPointer();
297  vtkIdType numCols = table->GetNumberOfColumns();
298  for (vtkIdType cc = 0; cc < numCols; ++cc)
299  {
300  std::string columnName = table->GetColumnName(cc);
301  auto roles = this->GetSeriesRoles(tableName, columnName);
302 
303  for (const auto& role : roles)
304  {
305  // recover the order of the current table column
306  const int order =
307  this->GetSeriesParameter(self, tableName, columnName, role, this->SeriesOrder, -1);
308 
309  // store all info in a (sorted) map
310  TableInfo info;
311  info.TableName = tableName;
312  info.ColumnName = columnName;
313  info.Role = role;
314  info.Block = tablesIter->second.second;
315  orderMap.insert(std::make_pair(order, std::make_pair(tablesIter->second.first, info)));
316  }
317  }
318  }
319 
320  // for each ordered column
321  for (auto it = orderMap.begin(); it != orderMap.end(); ++it)
322  {
323  vtkTable* table = it->second.first;
324  const TableInfo& info = it->second.second;
325 
327  this->SeriesPlots.GetPlot(self, info.TableName, info.ColumnName, info.Role);
328  if (!plot)
329  {
330  // Create the plot in the right order
331  plot = this->NewPlot(self, info.TableName, info.ColumnName, info.Role, info.Block);
332  if (!plot)
333  {
334  continue;
335  }
336  }
337  plot->SetInputData(table);
338  plot->SetUseIndexForXSeries(self->GetUseIndexForXAxis());
339  plot->SetInputArray(0, self->GetXAxisSeriesName());
340  plot->SetInputArray(
341  this->GetInputArrayIndex(info.TableName, info.ColumnName, info.Role), info.ColumnName);
342  this->SeriesPlots.AddPlot(self, info.TableName, info.ColumnName, info.Role, plot);
343  newPlots.AddPlot(self, info.TableName, info.ColumnName, info.Role, plot);
344  }
345 
346  // Remove any plots in this->SeriesPlots that are not in newPlots.
347  this->SeriesPlots.Intersect(newPlots, chartXY);
348  }
349 
350  //---------------------------------------------------------------------------
355  {
356  vtkChartXY* chartXY = self->GetChart();
357  vtkPlot* lastFunctionalBagPlot = nullptr;
358  for (PlotsMap::iterator iter1 = this->SeriesPlots.begin(); iter1 != this->SeriesPlots.end();
359  ++iter1)
360  {
361  for (PlotsMapItem::const_iterator iter2 = iter1->second.begin(); iter2 != iter1->second.end();
362  ++iter2)
363  {
364  const PlotInfo& plotInfo = iter2->second;
365  const std::string& tableName = plotInfo.TableName;
366  const std::string& columnName = plotInfo.ColumnName;
367  vtkPlot* plot = plotInfo.Plot;
368  const std::string& role = iter2->first;
369 
370  if (this->UpdateSinglePlotProperties(self, tableName, columnName, role, plot))
371  {
372  // Functional bag plots shall be stacked under the other plots.
374  if (plotBag)
375  {
376  // We can't select the median line as it may not exist in other dataset.
377  if (columnName == "QMedianLine")
378  {
379  plotBag->SelectableOff();
380  }
381  if (plotBag->IsBag())
382  {
383  if (!lastFunctionalBagPlot)
384  {
385  chartXY->LowerPlot(plotBag);
386  }
387  else
388  {
389  chartXY->StackPlotAbove(plotBag, lastFunctionalBagPlot);
390  }
391  lastFunctionalBagPlot = plotBag;
392  }
393  }
394  }
395  }
396  }
397  }
398 
399  //---------------------------------------------------------------------------
403  virtual bool Export(vtkXYChartRepresentation* self, vtkCSVExporter* exporter)
404  {
405  for (PlotsMap::iterator iter1 = this->SeriesPlots.begin(); iter1 != this->SeriesPlots.end();
406  ++iter1)
407  {
408  for (PlotsMapItem::const_iterator iter2 = iter1->second.begin(); iter2 != iter1->second.end();
409  ++iter2)
410  {
411  const PlotInfo& plotInfo = iter2->second;
412  vtkPlot* plot = plotInfo.Plot;
413  if (!plot->GetVisible())
414  {
415  continue;
416  }
417  const std::string& columnName = plotInfo.ColumnName;
418  vtkTable* table = plot->GetInput();
419  vtkDataArray* xarray = self->GetUseIndexForXAxis()
420  ? nullptr
421  : vtkDataArray::SafeDownCast(table->GetColumnByName(self->GetXAxisSeriesName()));
422  vtkAbstractArray* yarray = table->GetColumnByName(columnName.c_str());
423  if (yarray != nullptr)
424  {
425  exporter->AddColumn(yarray, plot->GetLabel().c_str(), xarray);
426  }
427  }
428  }
429  return true;
430  }
431 
432 protected:
433  //---------------------------------------------------------------------------
438  const std::string& tableName, const std::string& columnName, const std::string& role,
439  vtkPlot* plot)
440  {
441  vtkChartXY* chartXY = self->GetChart();
442  const bool visible =
443  this->GetSeriesParameter(self, tableName, columnName, role, this->SeriesVisibilities, false);
444  plot->SetVisible(visible);
445  if (!visible)
446  {
447  return false;
448  }
449 
450  std::string default_label = self->GetDefaultSeriesLabel(tableName, columnName);
451  std::string label =
452  this->GetSeriesParameter(self, tableName, columnName, role, this->Labels, default_label);
453  if (self->GetSeriesLabelPrefix())
454  {
455  label = std::string(self->GetSeriesLabelPrefix()) + label;
456  }
457  plot->SetLabel(label);
458 
460  self, tableName, columnName, role, this->Colors, vtkColor3d(0, 0, 0));
461  double opacity =
462  this->GetSeriesParameter(self, tableName, columnName, role, this->Opacities, 1.0);
463  plot->SetColorF(color.GetRed(), color.GetGreen(), color.GetBlue(), opacity);
464  plot->GetSelectionPen()->SetColorF(self->SelectionColor);
465 
466  plot->SetWidth(
467  this->GetSeriesParameter(self, tableName, columnName, role, this->LineThicknesses, 2));
468  plot->GetPen()->SetLineType(this->GetSeriesParameter(
469  self, tableName, columnName, role, this->LineStyles, static_cast<int>(vtkPen::SOLID_LINE)));
470 
471  if (vtkPlotPoints* plotPoints = vtkPlotPoints::SafeDownCast(plot))
472  {
473  plotPoints->SetMarkerStyle(this->GetSeriesParameter(self, tableName, columnName, role,
474  this->MarkerStyles, static_cast<int>(vtkPlotPoints::NONE)));
475  plotPoints->SetMarkerSize(
476  this->GetSeriesParameter(self, tableName, columnName, role, this->MarkerSizes, 1.0));
477  // the vtkValidPointMask array is used by some filters (like plot
478  // over line) to indicate invalid points. this instructs the line
479  // plot to not render those points
480  plotPoints->SetValidPointMaskName("vtkValidPointMask");
481  }
482 
483  chartXY->SetPlotCorner(
484  plot, this->GetSeriesParameter(self, tableName, columnName, role, this->AxisCorners, 0));
485 
486  // for now only vtkPlotBar has color mapping
487  vtkPlotBar* plotBar = vtkPlotBar::SafeDownCast(plot);
488  if (plotBar && columnName == "bin_values")
489  {
490  bool colorMapping =
491  this->GetSeriesParameter(self, tableName, columnName, role, this->UseColorMapping, false);
492  plotBar->SetScalarVisibility(colorMapping);
493  plotBar->SelectColorArray("bin_extents");
495  self, tableName, columnName, role, this->Lut, static_cast<vtkScalarsToColors*>(nullptr));
496  if (lut)
497  {
498  plotBar->SetLookupTable(lut);
499  }
500  }
501  return true;
502  }
503 };
504 
505 #endif
506 // VTK-HeaderTest-Exclude: vtkXYChartRepresentationInternals.h
color
std::map< std::string, vtkScalarsToColors * > Lut
order
bool RemovePlot(vtkChartRepresentation *self, const std::string &tableName, const std::string &columnName, const std::string &role=std::string())
void AddColumn(vtkAbstractArray *yarray, const char *yarrayname=nullptr, vtkDataArray *xarray=nullptr)
In STREAM_COLUMNS mode, use this method to add a column (yarray).
static vtkDataArray * SafeDownCast(vtkObjectBase *o)
T GetSeriesParameter(vtkXYChartRepresentation *self, const std::string &tableName, const std::string &columnName, const std::string &vtkNotUsed(role), const std::map< std::string, T > &parameter_map, const T default_value=T()) const
Makes is easy to obtain a value for a series parameter, is set, else the default. ...
virtual void SetWidth(float width)
const double & GetBlue() const
vtkXYChartRepresentation is representation that is used to add vtkPlot subclasses to a vtkChartXY ins...
void AddPlot(vtkChartRepresentation *self, const std::string &tableName, const std::string &columnName, const std::string &role, vtkPlot *plot)
info
vtkXYChartRepresentation::MapOfTables MapOfTables
static vtkPlotFunctionalBag * SafeDownCast(vtkObjectBase *o)
int vtkIdType
virtual std::vector< std::string > GetSeriesRoles(const std::string &vtkNotUsed(tableName), const std::string &vtkNotUsed(columnName))
Subclasses can override this method to assign a role for a specific data array in the input dataset...
void SetPlotCorner(vtkPlot *plot, int corner)
virtual int GetInputArrayIndex(const std::string &vtkNotUsed(tableName), const std::string &vtkNotUsed(columnName), const std::string &vtkNotUsed(role))
const double & GetRed() const
virtual bool UpdateSinglePlotProperties(vtkXYChartRepresentation *self, const std::string &tableName, const std::string &columnName, const std::string &role, vtkPlot *plot)
Returns false for in-visible plots.
vtkPen * GetPen()
vtkSmartPointer< vtkPlot > GetPlot(vtkChartRepresentation *self, const std::string &tableName, const std::string &columnName, const std::string &role=std::string()) const
virtual void SetLookupTable(vtkScalarsToColors *lut)
std::map< std::string, std::pair< vtkSmartPointer< vtkTable >, unsigned int > > MapOfTables
vtkAbstractArray * GetColumnByName(const char *name)
virtual vtkPlot * AddPlot(int type)
void RemoveAllPlots(vtkChartXY *chartXY)
Destroy all vtkPlot instances.
static vtkPlotPoints * SafeDownCast(vtkObjectBase *o)
const char * GetColumnName(vtkIdType col)
virtual bool RemovePlotInstance(vtkPlot *plot)
virtual void UpdatePlotProperties(vtkXYChartRepresentation *self)
Update properties for plots in the chart.
virtual bool IsBag()
virtual vtkTable * GetInput()
virtual void SetInputArray(int index, const vtkStdString &name)
vtkIdType LowerPlot(vtkPlot *plot)
virtual void SetScalarVisibility(bool)
virtual void SetInputData(vtkTable *table)
virtual vtkIdType StackPlotAbove(vtkPlot *plot, vtkPlot *under)
virtual vtkStdString GetLabel()
virtual void UpdatePlots(vtkXYChartRepresentation *self, const MapOfTables &tables)
Update i.e.
void SelectColorArray(vtkIdType arrayNum)
vtkChartRepresentation is the base representation for charting representations.
void SetColorF(double color[3])
virtual void SetUseIndexForXSeries(bool)
exporter used by certain views to export data as CSV.
static vtkPlotBar * SafeDownCast(vtkObjectBase *o)
vtkPen * GetSelectionPen()
virtual bool Export(vtkXYChartRepresentation *self, vtkCSVExporter *exporter)
Export visible plots to a CSV file.
vtkIdType GetNumberOfColumns()
virtual void SetVisible(bool)
virtual void SetLabel(const vtkStdString &label)
virtual vtkPlot * NewPlot(vtkXYChartRepresentation *self, const std::string &tableName, const std::string &columnName, const std::string &role, unsigned int block=0)
Add new plot.
void SetLineType(int type)
virtual bool GetVisible()
void Intersect(const PlotsMap &other, vtkChartXY *chartXY)
const double & GetGreen() const
virtual void SelectableOff()
key