xwavengraph.cpp
1 /***************************************************************************
2  Copyright (C) 2002-2015 Kentaro Kitagawa
3  kitagawa@phys.s.u-tokyo.ac.jp
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  You should have received a copy of the GNU Library General
11  Public License and a list of authors along with this program;
12  see the files COPYING and AUTHORS.
13  ***************************************************************************/
14 #include "xwavengraph.h"
15 
16 #include "ui_graphnurlform.h"
17 #include "graphwidget.h"
18 #include "graph.h"
19 
20 #include <QPushButton>
21 #include <QStatusBar>
22 
23 #define OFSMODE (std::ios::out | std::ios::app | std::ios::ate)
24 
25 //---------------------------------------------------------------------------
26 
27 XWaveNGraph::XWaveNGraph(const char *name, bool runtime, FrmGraphNURL *item) :
28  XNode(name, runtime), m_btnDump(item->m_btnDump), m_graph(create<XGraph> (
29  name, false)), m_dump(create<XTouchableNode> ("Dump", true)), m_filename(create<
30  XStringNode> ("FileName", true)) {
31  item->m_graphwidget->setGraph(m_graph);
32  m_conFilename = xqcon_create<XFilePathConnector> (m_filename, item->m_edUrl, item->m_btnUrl,
33  "Data files (*.dat);;All files (*.*)", true);
34  m_conDump = xqcon_create<XQButtonConnector> (m_dump, item->m_btnDump);
35  init();
36 }
37 XWaveNGraph::XWaveNGraph(const char *name, bool runtime, XQGraph *graphwidget,
38  QLineEdit *ed, QAbstractButton *btn, QPushButton *btndump) :
39  XNode(name, runtime), m_btnDump(btndump), m_graph(create<XGraph> (name,
40  false)), m_dump(create<XTouchableNode> ("Dump", true)), m_filename(create<
41  XStringNode> ("FileName", true)) {
42  graphwidget->setGraph(m_graph);
43  m_conFilename = xqcon_create<XFilePathConnector> (m_filename, ed, btn,
44  "Data files (*.dat);;All files (*.*)", true);
45  m_conDump = xqcon_create<XQButtonConnector> (m_dump, btndump);
46  init();
47 }
48 void XWaveNGraph::init() {
49  iterate_commit([=](Transaction &tr){
50  m_lsnOnFilenameChanged = tr[ *filename()].onValueChanged().connectWeakly(
51  shared_from_this(), &XWaveNGraph::onFilenameChanged);
52  });
53 
54  iterate_commit([=](Transaction &tr){
55  m_lsnOnIconChanged = tr[ *this].onIconChanged().connectWeakly(
56  shared_from_this(),
57  &XWaveNGraph::onIconChanged, XListener::FLAG_MAIN_THREAD_CALL
58  | XListener::FLAG_AVOID_DUP);
59  tr.mark(tr[ *this].onIconChanged(), false);
60 
61  tr[ *dump()].setUIEnabled(false);
62  tr[ *m_graph->persistence()] = 0.0;
63  tr[ *this].clearPlots();
64  });
65 }
66 XWaveNGraph::~XWaveNGraph() {
67  m_stream.close();
68 }
69 
70 void
71 XWaveNGraph::Payload::clearPoints() {
72  setRowCount(0);
73  for(int i = 0; i < numPlots(); ++i)
74  tr()[ *plot(i)].points().clear();
75 
76  shared_ptr<XGraph> graph(static_cast<XWaveNGraph*>( &node())->graph());
77  tr().mark(tr()[ *graph].onUpdate(), graph.get());
78 }
79 void
80 XWaveNGraph::Payload::clearPlots() {
81  const auto &graph(static_cast<XWaveNGraph &>(node()).m_graph);
82  for(auto it = m_plots.begin(); it != m_plots.end(); it++) {
83  graph->plots()->release(tr(), it->xyplot);
84  }
85  if(m_axisw)
86  graph->axes()->release(tr(), m_axisw);
87  if(m_axisz)
88  graph->axes()->release(tr(), m_axisz);
89  if(m_axisy2)
90  graph->axes()->release(tr(), m_axisy2);
91 
92  if(m_axisx)
93  tr()[ *m_axisx->label()] = "";
94  if(m_axisy)
95  tr()[ *m_axisy->label()] = "";
96  m_plots.clear();
97  m_axisy2.reset();
98  m_axisz.reset();
99  m_axisw.reset();
100  m_colw = -1;
101 }
102 void
103 XWaveNGraph::Payload::insertPlot(const XString &label, int x, int y1, int y2,
104  int weight, int z) {
105  const auto &graph(static_cast<XWaveNGraph &>(node()).m_graph);
106  assert( (y1 < 0) || (y2 < 0) );
107  Plot plot;
108  plot.colx = x;
109  plot.coly1 = y1;
110  plot.coly2 = y2;
111  plot.colweight = weight;
112  plot.colz = z;
113 
114  if(weight >= 0) {
115  if((m_colw >= 0) && (m_colw != weight))
116  m_colw = -1;
117  else
118  m_colw = weight;
119  }
120 
121  // graph->setName(getName());
122  tr()[ *graph->label()] = node().getLabel();
123 
124  unsigned int plotnum = m_plots.size() + 1;
125  plot.xyplot = graph->plots()->create<XXYPlot>(tr(), formatString("Plot%u",
126  plotnum).c_str(), true, ref(tr()), graph);
127 
128  tr()[ *plot.xyplot->label()] = label;
129  const XNode::NodeList &axes_list( *tr().list(graph->axes()));
130  m_axisx = static_pointer_cast<XAxis>(axes_list.at(0));
131  m_axisy = static_pointer_cast<XAxis>(axes_list.at(1));
132  tr()[ *plot.xyplot->axisX()] = m_axisx;
133  tr()[ *m_axisx->label()] = m_labels[plot.colx];
134  if(plot.coly1 >= 0) {
135  tr()[ *plot.xyplot->axisY()] = m_axisy;
136  tr()[ *m_axisy->label()] = m_labels[plot.coly1];
137  }
138  tr()[ *plot.xyplot->maxCount()] = rowCount();
139  tr()[ *plot.xyplot->maxCount()] = false;
140  tr()[ *plot.xyplot->clearPoints()].setUIEnabled(false);
141  tr()[ *plot.xyplot->intensity()] = 1.0;
142  if(m_plots.size()) {
143  tr()[ *plot.xyplot->pointColor()] = clGreen;
144  tr()[ *plot.xyplot->lineColor()] = clGreen;
145  tr()[ *plot.xyplot->barColor()] = clGreen;
146  tr()[ *plot.xyplot->displayMajorGrid()] = false;
147  }
148 
149  if(plot.colz >= 0) {
150  if( !m_axisz) {
151  m_axisz = graph->axes()->create<XAxis>(tr(), "Z Axis", true,
152  XAxis::DirAxisZ, true, ref(tr()), graph);
153  }
154  tr()[ *plot.xyplot->axisZ()] = m_axisz;
155  tr()[ *m_axisz->label()] = m_labels[plot.colz];
156  }
157  if(plot.colweight >= 0) {
158  if( !m_axisw) {
159  m_axisw = graph->axes()->create<XAxis>(tr(), "Weight", true,
160  XAxis::AxisWeight, true, ref(tr()), graph);
161  }
162  tr()[ *m_axisw->autoScale()] = false;
163  tr()[ *m_axisw->autoScale()].setUIEnabled(false);
164  tr()[ *plot.xyplot->axisW()] = m_axisw;
165  tr()[ *m_axisw->label()] = m_labels[plot.colweight];
166  }
167  if(plot.coly2 >= 0) {
168  if( !m_axisy2) {
169  m_axisy2 = graph->axes()->create<XAxis>(tr(), "Y2 Axis", true,
170  XAxis::DirAxisY, true, ref(tr()), graph);
171  }
172  tr()[ *plot.xyplot->axisY()] = m_axisy2;
173  tr()[ *m_axisy2->label()] = m_labels[plot.coly2];
174  }
175 
176  m_plots.push_back(plot);
177 }
178 
179 void
180 XWaveNGraph::Payload::setColCount(unsigned int n, const char **labels) {
181  m_colcnt = n;
182  m_labels.resize(m_colcnt);
183  for(unsigned int i = 0; i < n; i++) {
184  m_labels[i] = labels[i];
185  }
186 }
187 void
188 XWaveNGraph::Payload::setLabel(unsigned int col, const char *label) {
189  m_labels[col] = label;
190 }
191 void
192 XWaveNGraph::Payload::setRowCount(unsigned int n) {
193  m_cols.resize(m_colcnt * n);
194  for(auto it = m_plots.begin(); it != m_plots.end(); it++) {
195  tr()[ *it->xyplot->maxCount()] = n;
196  }
197 }
198 double *
199 XWaveNGraph::Payload::cols(unsigned int n) {
200  return rowCount() ? &(m_cols[rowCount() * n]) : 0;
201 }
202 const double *
203 XWaveNGraph::Payload::cols(unsigned int n) const {
204  return rowCount() ? &(m_cols[rowCount() * n]) : 0;
205 }
206 const double *
207 XWaveNGraph::Payload::weight() const {
208  if(m_colw < 0) return 0L;
209  return cols(m_colw);
210 }
211 
212 void
213 XWaveNGraph::onIconChanged(const Snapshot &shot, bool v) {
214  if( !m_conDump->isAlive()) return;
215  if( !v)
216  m_btnDump->setIcon(QApplication::style()->
217  standardIcon(QStyle::SP_DialogSaveButton));
218  else
219  m_btnDump->setIcon(QApplication::style()->
220  standardIcon(QStyle::SP_BrowserReload));
221 }
222 void
223 XWaveNGraph::onFilenameChanged(const Snapshot &shot, XValueNodeBase *) {
224  {
225  XScopedLock<XMutex> lock(m_filemutex);
226 
227  if(m_stream.is_open())
228  m_stream.close();
229  m_stream.clear();
230  m_stream.open(
231  (const char*)QString(shot[ *filename()].to_str().c_str()).toLocal8Bit().data(),
232  OFSMODE);
233 
234  iterate_commit([=](Transaction &tr){
235  if(m_stream.good()) {
236  m_lsnOnDumpTouched = tr[ *dump()].onTouch().connectWeakly(
237  shared_from_this(), &XWaveNGraph::onDumpTouched);
238  tr[ *dump()].setUIEnabled(true);
239  }
240  else {
241  m_lsnOnDumpTouched.reset();
242  tr[ *dump()].setUIEnabled(false);
243  gErrPrint(i18n("Failed to open file."));
244  }
245  tr.mark(tr[ *this].onIconChanged(), false);
246  });
247  }
248 }
249 
250 void
251 XWaveNGraph::onDumpTouched(const Snapshot &, XTouchableNode *) {
252  Snapshot shot( *this);
253  {
254  XScopedLock<XMutex> filelock(m_filemutex);
255  if( !m_stream.good()) return;
256 
257  int rowcnt = shot[ *this].rowCount();
258  int colcnt = shot[ *this].colCount();
259 
260  m_stream << "#";
261  for(unsigned int i = 0; i < colcnt; i++) {
262  m_stream << shot[ *this].labels()[i] << KAME_DATAFILE_DELIMITER;
263  }
264 // stream << std::endl;
265  m_stream << "#at " << (XTime::now()).getTimeFmtStr(
266  "%Y/%m/%d %H:%M:%S") << std::endl;
267 
268  auto &p(shot[ *this]);
269  for(unsigned int i = 0; i < rowcnt; i++) {
270  if( !p.weight() || (p.weight()[i] > 0)) {
271  for(unsigned int j = 0; j < colcnt; j++) {
272  m_stream << p.cols(j)[i] << KAME_DATAFILE_DELIMITER;
273  }
274  m_stream << std::endl;
275  }
276  }
277  m_stream << std::endl;
278 
279  m_stream.flush();
280  }
281 
282  iterate_commit([=](Transaction &tr){
283  tr.mark(tr[ *this].onIconChanged(), true);
284  });
285 }
286 void XWaveNGraph::drawGraph(Transaction &tr) {
287  const Snapshot &shot(tr);
288  for(int i = 0; i < shot[ *this].numPlots(); ++i) {
289  int rowcnt = shot[ *this].rowCount();
290  double *colx = tr[ *this].cols(shot[ *this].colX(i));
291  double *coly = NULL;
292  if(shot[ *this].colY1(i) >= 0)
293  coly = tr[ *this].cols(shot[ *this].colY1(i));
294  if(shot[ *this].colY2(i) >= 0)
295  coly = tr[ *this].cols(shot[ *this].colY2(i));
296  double *colweight = (shot[ *this].colWeight(i) >= 0) ? tr[ *this].cols(shot[ *this].colWeight(i)) : NULL;
297  double *colz = (shot[ *this].colZ(i) >= 0) ? tr[ *this].cols(shot[ *this].colZ(i)) : NULL;
298 
299  if(colweight) {
300  double weight_max = 0.0;
301  for(int i = 0; i < rowcnt; i++)
302  weight_max = std::max(weight_max, colweight[i]);
303  tr[ *shot[ *this].axisw()->maxValue()] = weight_max;
304  tr[ *shot[ *this].axisw()->minValue()] = -0.4 * weight_max;
305  }
306 
307  auto &points_plot(tr[ *shot[ *this].plot(i)].points());
308  points_plot.clear();
309  for(int i = 0; i < rowcnt; ++i) {
310  double z = 0.0;
311  if(colz)
312  z = colz[i];
313  if(colweight) {
314  if(colweight[i] > 0)
315  points_plot.push_back(XGraph::ValPoint(colx[i],
316  coly[i], z, colweight[i]));
317  }
318  else
319  points_plot.push_back(XGraph::ValPoint(colx[i], coly[i], z));
320  }
321  }
322  tr.mark(tr[ *m_graph].onUpdate(), m_graph.get());
323 }

Generated for KAME4 by  doxygen 1.8.3