source: src/UIElements/Views/Qt4/QtHomologyList.cpp

stable v1.7.0
Last change on this file was 476781, checked in by Frederik Heber <frederik.heber@…>, 2 months ago

FIX: fixes several issues in QtHomologyList related to plotting.

  • the curve was added twice: once through the signal from QSeisCurveRegistry and the second time through a direct call. The latter is now removed.
  • We now plot all potentials (not just harmonic bond) by using default xvalues for constant. The harmonic bond was plotted because the bond length appeared twice in the exemplary water molecule while the harmonic angle appears only once. This is also fixed.
  • Property mode set to 100644
File size: 11.6 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2013 Frederik Heber. All rights reserved.
5 *
6 *
7 * This file is part of MoleCuilder.
8 *
9 * MoleCuilder is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * MoleCuilder is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/*
24 * QtHomologyList.cpp
25 *
26 * Created on: Jun 24, 2013
27 * Author: heber
28 */
29
30// include config.h
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
35#include "Views/Qt4/QtHomologyList.hpp"
36#include "Views/Qt4/QtNumericalItem.hpp"
37
38#include <QtGui/QAbstractItemView>
39#include <QtGui/QTreeWidget>
40#include <QtGui/QTabWidget>
41#include <Qt/qsettings.h>
42#include <Qt/qsplitter.h>
43#include <Qt/qboxlayout.h>
44
45//#include "CodePatterns/MemDebug.hpp"
46
47#include <iterator>
48#include <iostream>
49
50#include <boost/assign.hpp>
51
52#include "CodePatterns/Log.hpp"
53
54#include "Fragmentation/Homology/HomologyContainer.hpp"
55#include "FunctionApproximation/FunctionModel.hpp"
56#include "FunctionApproximation/TrainingData.hpp"
57#include "Potentials/CompoundPotential.hpp"
58#include "Potentials/EmpiricalPotential.hpp"
59#include "Potentials/InternalCoordinates/Coordinator.hpp"
60#include "Potentials/PotentialRegistry.hpp"
61#ifdef HAVE_QWT
62#include "UIElements/Views/Qt4/Plotting/QSeisData.hpp"
63#include "UIElements/Views/Qt4/Plotting/QSeisPageRegistry.hpp"
64#include "UIElements/Views/Qt4/Plotting/QSeisPlotCurve.hpp"
65#include "UIElements/Views/Qt4/Plotting/QSeisPlotPage.hpp"
66#include "UIElements/Views/Qt4/Plotting/QSeisCurveRegistry.hpp"
67#endif
68#include "World.hpp"
69
70using namespace std;
71
72using namespace boost::assign;
73
74const int QtHomologyList::COLUMNCOUNT = COLUMNTYPES_MAX;
75const char *QtHomologyList::COLUMNNAMES[QtHomologyList::COLUMNCOUNT]={"Number","Nodes","Edges","Occurrence"};
76
77QtHomologyList::QtHomologyList(QWidget * _parent) :
78 QWidget(_parent),
79 Observer("QtHomologyList"),
80 homologycontainer_enabled(false),
81 potentialregistry_enabled(false)
82{
83 QHBoxLayout* layout = new QHBoxLayout(this);
84 QSplitter *splitter = new QSplitter (Qt::Horizontal, this );
85 layout->addWidget(splitter);
86
87 // tree widget
88 treewidget = new QTreeWidget (splitter);
89 treewidget->setSelectionMode( QTreeWidget::SingleSelection );
90 treewidget->setColumnCount(COLUMNCOUNT);
91 treewidget->setSortingEnabled(true);
92 //treewidget->setSizePolicy( QSizePolicy::Minimum, sizePolicy().verticalPolicy() );
93 QStringList header;
94 for(int i=0; i<COLUMNCOUNT;++i)
95 header << COLUMNNAMES[i];
96 treewidget->setHeaderLabels(header);
97 treewidget->sortByColumn(0);
98 splitter->addWidget(treewidget);
99
100 // plot widget
101#ifdef HAVE_QWT
102 widget = new QSeisPlotPage ("energy", splitter);
103 //widget->setSizePolicy( QSizePolicy::MinimumExpanding, sizePolicy().verticalPolicy() );
104 QSeisPageRegistry::getInstance().registerInstance(widget);
105#else
106 widget = new QWidget(splitter);
107#endif
108 splitter->addWidget(widget);
109
110 dirty = true;
111
112 QSettings settings;
113 settings.beginGroup("QtHomologyList");
114 treewidget->resize(settings.value("treewidget_size", QSize(width()/2, 20)).toSize());
115 widget->resize(settings.value("plotwidget_size", QSize(width()/2, 20)).toSize());
116 settings.endGroup();
117
118
119 HomologyContainer &homologies = World::getInstance().getHomologies();
120 homologies.signOn(this);
121 homologycontainer_enabled = true;
122 PotentialRegistry::getInstance().signOn(this);
123 potentialregistry_enabled = true;
124
125#ifdef HAVE_QWT
126 //connect the PlotCurveRegistry directly to the PlotPage registry
127 connect(QSeisCurveRegistry::getPointer(), SIGNAL(curveAdded(std::string, QString)), QSeisPageRegistry::getPointer(), SLOT(addCurve(std::string, QString)));
128 connect(QSeisCurveRegistry::getPointer(), SIGNAL(curveRemoved(std::string, QString)), QSeisPageRegistry::getPointer(), SLOT(removeCurve(std::string, QString)));
129 connect(QSeisCurveRegistry::getPointer(), SIGNAL(curveChanged(std::string, QString)), QSeisPageRegistry::getPointer(), SLOT(updateCurve(std::string, QString)));
130#endif
131
132 connect(treewidget,SIGNAL(itemSelectionChanged()),this,SLOT(rowSelected()));
133 connect(this,SIGNAL(changed()),this,SLOT(update()));
134 connect(this,SIGNAL(needsRefill()),this,SLOT(refill()), Qt::QueuedConnection);
135
136 emit needsRefill();
137}
138
139QtHomologyList::~QtHomologyList()
140{
141 QSettings settings;
142 settings.beginGroup("QtHomologyList");
143 settings.setValue("treewidget_size", treewidget->size());
144 settings.setValue("plotwidget_size", widget->size());
145 settings.endGroup();
146
147
148 if (homologycontainer_enabled) {
149 HomologyContainer &homologies = World::getInstance().getHomologies();
150 homologies.signOff(this);
151 }
152 if (potentialregistry_enabled)
153 PotentialRegistry::getInstance().signOff(this);
154}
155
156void QtHomologyList::update(Observable *publisher)
157{
158 dirty = true;
159
160 // force an update from Qt...
161// treewidget->clear();
162 emit changed(); //doesn't work!?!
163}
164
165void QtHomologyList::refill()
166{
167 boost::recursive_mutex::scoped_lock lock(refill_mutex);
168
169 const HomologyContainer &homologies = World::getInstance().getHomologies();
170
171 // clear everything
172 HomologySelection.clear();
173 treewidget->clear();
174#ifdef HAVE_QWT
175 QSeisCurveRegistry::getInstance().resetRegistry();
176#endif
177
178 size_t count = 0;
179 for (HomologyContainer::const_key_iterator homologyiter = homologies.key_begin();
180 homologyiter != homologies.key_end();
181 homologyiter = homologies.getNextKey(homologyiter), ++count) {
182 HomologyContainer::range_t occurences = homologies.getHomologousGraphs(*homologyiter);
183 const HomologyGraph &graph = occurences.first->first;
184 const size_t times = std::distance(occurences.first, occurences.second);
185
186 // create item
187 std::vector<int> numerical_columns;
188 numerical_columns += OCCURRENCE;
189 QTreeWidgetItem *treeItem = new QtNumericalItem(NUMBER, numerical_columns, treewidget);
190 treeItem->setText(NUMBER, QString::number(count));
191 {
192 std::stringstream output;
193 graph.printNodes(output);
194 treeItem->setText(NODES, QString(output.str().c_str()));
195 }
196 {
197 std::stringstream output;
198 graph.printEdges(output);
199 treeItem->setText(EDGES, QString(output.str().c_str()));
200 }
201 if (times > 0) {
202 treeItem->setText(OCCURRENCE, QString::number(times));
203 } else {
204 treeItem->setText(OCCURRENCE, "none");
205 treeItem->setDisabled(true);
206 }
207 HomologySelection.push_back(treeItem->isSelected());
208
209#ifdef HAVE_QWT
210 // create associated curve in plot
211 CompoundPotential *compound = new CompoundPotential(graph);
212 ASSERT( compound != NULL,
213 "QtHomologyList::refill() - compound is NULL.");
214 TrainingData data(compound->getSpecificFilter());
215 data(homologies.getHomologousGraphs(graph));
216 if (!data.getTrainingInputs().empty()) {
217 // generate QSeisData
218 const TrainingData::InputVector_t &inputs = data.getAllArguments();
219 const TrainingData::OutputVector_t &outputs = data.getTrainingOutputs();
220 std::vector<double> xvalues;
221 std::vector<double> yvalues;
222
223 // go through each potential
224 for (CompoundPotential::models_t::const_iterator potiter = compound->begin();
225 potiter != compound->end();
226 ++potiter) {
227 const EmpiricalPotential &potential = dynamic_cast<const EmpiricalPotential &>(**potiter);
228 const std::string potentialname = potential.getName();
229 const FunctionModel::filter_t filter = potential.getSpecificFilter();
230 Coordinator::ptr coordinator = potential.getCoordinator();
231 // then we need to sample the potential
232 HomologyGraph dummy;
233
234 xvalues.clear();
235 yvalues.clear();
236 for (TrainingData::OutputVector_t::const_iterator outputiter = outputs.begin();
237 outputiter != outputs.end(); ++outputiter)
238 yvalues.push_back((*outputiter)[0]);
239 for (TrainingData::InputVector_t::const_iterator inputiter = inputs.begin();
240 inputiter != inputs.end(); ++inputiter) {
241 const FunctionModel::list_of_arguments_t specificargs = filter(dummy, *inputiter);
242 double average = 0.;
243 for (FunctionModel::list_of_arguments_t::const_iterator argiter = specificargs.begin();
244 argiter != specificargs.end(); ++argiter) {
245 const FunctionModel::arguments_t args = *argiter;
246 average += (*coordinator)(args);
247 }
248 const size_t index = xvalues.size();
249 if (specificargs.size() > 1) {
250 xvalues.push_back(average/(double)specificargs.size());
251 } else if (specificargs.size() == 1) {
252 xvalues.push_back(average);
253 } else {
254 xvalues.push_back(index/0.1);
255 }
256 }
257
258 // We need to sort the xvalues (and associated yvalues also)
259 std::vector<double>::const_iterator xiter = xvalues.begin();
260 std::vector<double>::const_iterator yiter = yvalues.begin();
261 std::map<double, std::set<double> > sorted_xy;
262 for (;xiter != xvalues.end(); ++xiter, ++yiter) {
263 std::set<double> yset;
264 yset.insert(*yiter);
265 std::pair<std::map<double, std::set<double> >::iterator, bool> inserter =
266 sorted_xy.insert(std::make_pair(*xiter, yset));
267 if (!inserter.second)
268 inserter.first->second.insert(*yiter);
269 }
270 xvalues.clear();
271 yvalues.clear();
272 for (std::map<double, std::set<double> >::const_iterator iter = sorted_xy.begin();
273 iter != sorted_xy.end(); ++iter) {
274 for (std::set<double>::const_iterator valueiter = iter->second.begin();
275 valueiter != iter->second.end();
276 ++valueiter) {
277 xvalues.push_back(iter->first);
278 yvalues.push_back(*valueiter);
279 }
280 }
281
282 if ((!xvalues.empty()) && (!yvalues.empty())) {
283 QSeisData data(xvalues, yvalues, QString(potentialname.c_str()));
284 // couple to QSeisPlotCurve and register the curve
285 QSeisPlotCurve *curve = new QSeisPlotCurve(QString(potentialname.c_str()), "energy");
286 curve->updateCurve(&data);
287 if (!QSeisCurveRegistry::getInstance().isPresentByName(curve->getName()))
288 QSeisCurveRegistry::getInstance().registerInstance(curve);
289 else
290 delete curve;
291 }
292 }
293 }
294#endif
295 }
296 dirty = false;
297}
298
299void QtHomologyList::paintEvent(QPaintEvent * event)
300{
301 boost::recursive_mutex::scoped_lock lock(refill_mutex);
302
303 if (dirty)
304 refill();
305// treewidget->paintEvent(event);
306}
307
308void QtHomologyList::subjectKilled(Observable *publisher)
309{
310 // as a new instance should always already be present ... just sign on
311 if (static_cast<PotentialRegistry *>(publisher) == PotentialRegistry::getPointer()) {
312 potentialregistry_enabled = false;
313 } else if (static_cast<HomologyContainer *>(publisher) == &World::getInstance().getHomologies()) {
314 homologycontainer_enabled = false;
315 }
316}
317
318
319void QtHomologyList::rowSelected()
320{
321 boost::recursive_mutex::scoped_lock lock(refill_mutex);
322
323 //std::cout << "rowSelected\n";
324 for (int i=0;i<treewidget->topLevelItemCount();i++){
325 QTreeWidgetItem *item = treewidget->topLevelItem(i);
326 bool newSelection = item->isSelected();
327 if (newSelection != HomologySelection[i]){
328 // TODO: Add selected curve to QTabWidget
329 }
330 }
331}
332
Note: See TracBrowser for help on using the repository browser.