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

Gui_Fixes
Last change on this file since f62b00 was f62b00, checked in by Frederik Heber <heber@…>, 8 years ago

FIX: Skipping empty curves in QtHomologyList::refill().

  • this does not solve the whole problem. For a large molecule, we have many different graphs to the same "morse_61" potential, which appears then frequently in the plot list ... BUT each shows the data of the first/last plot curve as they are distinguished by name.
  • Property mode set to 100644
File size: 11.1 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 <iterator>
39#include <iostream>
40
41#include <QAbstractItemView>
42#include <QtGui/QTreeWidget>
43#include <QtGui/QTabWidget>
44#include <Qt/qsettings.h>
45#include <Qt/qsplitter.h>
46#include <Qt/qboxlayout.h>
47
48#include "CodePatterns/MemDebug.hpp"
49
50#include "CodePatterns/Log.hpp"
51
52#include "Fragmentation/Homology/HomologyContainer.hpp"
53#include "FunctionApproximation/FunctionModel.hpp"
54#include "FunctionApproximation/TrainingData.hpp"
55#include "Potentials/CompoundPotential.hpp"
56#include "Potentials/EmpiricalPotential.hpp"
57#include "Potentials/InternalCoordinates/Coordinator.hpp"
58#include "Potentials/PotentialRegistry.hpp"
59#ifdef HAVE_QWT
60#include "UIElements/Views/Qt4/Plotting/QSeisData.hpp"
61#include "UIElements/Views/Qt4/Plotting/QSeisPageRegistry.hpp"
62#include "UIElements/Views/Qt4/Plotting/QSeisPlotCurve.hpp"
63#include "UIElements/Views/Qt4/Plotting/QSeisPlotPage.hpp"
64#include "UIElements/Views/Qt4/Plotting/QSeisCurveRegistry.hpp"
65#endif
66#include "World.hpp"
67
68using namespace std;
69
70const int QtHomologyList::COLUMNCOUNT = COLUMNTYPES_MAX;
71const char *QtHomologyList::COLUMNNAMES[QtHomologyList::COLUMNCOUNT]={"Number","Nodes","Edges","Occurrence"};
72
73QtHomologyList::QtHomologyList(QWidget * _parent) :
74 QWidget(_parent),
75 Observer("QtHomologyList"),
76 potentialregistry_enabled(false)
77{
78 QHBoxLayout* layout = new QHBoxLayout(this);
79 QSplitter *splitter = new QSplitter (Qt::Horizontal, this );
80 layout->addWidget(splitter);
81
82 // tree widget
83 treewidget = new QTreeWidget (splitter);
84 treewidget->setSelectionMode( QTreeWidget::SingleSelection );
85 treewidget->setColumnCount(COLUMNCOUNT);
86 treewidget->setSortingEnabled(true);
87 //treewidget->setSizePolicy( QSizePolicy::Minimum, sizePolicy().verticalPolicy() );
88 QStringList header;
89 for(int i=0; i<COLUMNCOUNT;++i)
90 header << COLUMNNAMES[i];
91 treewidget->setHeaderLabels(header);
92 treewidget->sortByColumn(0);
93 splitter->addWidget(treewidget);
94
95 // plot widget
96#ifdef HAVE_QWT
97 widget = new QSeisPlotPage ("energy", splitter);
98 //widget->setSizePolicy( QSizePolicy::MinimumExpanding, sizePolicy().verticalPolicy() );
99 QSeisPageRegistry::getInstance().registerInstance(widget);
100#else
101 widget = new QWidget(splitter);
102#endif
103 splitter->addWidget(widget);
104
105 dirty = true;
106 clearing = false;
107
108 QSettings settings;
109 settings.beginGroup("QtHomologyList");
110 treewidget->resize(settings.value("treewidget_size", QSize(width()/2, 20)).toSize());
111 widget->resize(settings.value("plotwidget_size", QSize(width()/2, 20)).toSize());
112 settings.endGroup();
113
114
115 HomologyContainer &homologies = World::getInstance().getHomologies();
116 homologies.signOn(this);
117 PotentialRegistry::getInstance().signOn(this);
118 potentialregistry_enabled = true;
119
120#ifdef HAVE_QWT
121 //connect the PlotCurveRegistry directly to the PlotPage registry
122 connect(QSeisCurveRegistry::getPointer(), SIGNAL(curveAdded(std::string, QString)), QSeisPageRegistry::getPointer(), SLOT(addCurve(std::string, QString)));
123 connect(QSeisCurveRegistry::getPointer(), SIGNAL(curveRemoved(std::string, QString)), QSeisPageRegistry::getPointer(), SLOT(removeCurve(std::string, QString)));
124 connect(QSeisCurveRegistry::getPointer(), SIGNAL(curveChanged(std::string, QString)), QSeisPageRegistry::getPointer(), SLOT(updateCurve(std::string, QString)));
125#endif
126
127 connect(treewidget,SIGNAL(itemSelectionChanged()),this,SLOT(rowSelected()));
128 connect(this,SIGNAL(changed()),this,SLOT(update()));
129 connect(this,SIGNAL(needsRefill()),this,SLOT(refill()), Qt::QueuedConnection);
130
131 emit needsRefill();
132}
133
134QtHomologyList::~QtHomologyList()
135{
136 QSettings settings;
137 settings.beginGroup("QtHomologyList");
138 settings.setValue("treewidget_size", treewidget->size());
139 settings.setValue("plotwidget_size", widget->size());
140 settings.endGroup();
141
142
143 HomologyContainer &homologies = World::getInstance().getHomologies();
144 homologies.signOff(this);
145 if (potentialregistry_enabled)
146 PotentialRegistry::getInstance().signOff(this);
147}
148
149void QtHomologyList::update(Observable *publisher) {
150
151 dirty = true;
152
153 // force an update from Qt...
154// clearing = true;
155// treewidget->clear();
156// clearing = false;
157 emit changed(); //doesn't work!?!
158}
159
160void QtHomologyList::refill()
161{
162 clearing = true;
163 const HomologyContainer &homologies = World::getInstance().getHomologies();
164
165 // clear everything
166 HomologySelection.clear();
167 treewidget->clear();
168#ifdef HAVE_QWT
169 QSeisCurveRegistry::getInstance().resetRegistry();
170#endif
171
172 size_t count = 0;
173 for (HomologyContainer::const_key_iterator homologyiter = homologies.key_begin();
174 homologyiter != homologies.key_end();
175 homologyiter = homologies.getNextKey(homologyiter), ++count) {
176 HomologyContainer::range_t occurences = homologies.getHomologousGraphs(*homologyiter);
177 const HomologyGraph &graph = occurences.first->first;
178 const size_t times = std::distance(occurences.first, occurences.second);
179
180 // create item
181 QTreeWidgetItem *treeItem = new QtNumericalItem(NUMBER, treewidget);
182 treeItem->setText(NUMBER, QString::number(count));
183 {
184 std::stringstream output;
185 graph.printNodes(output);
186 treeItem->setText(NODES, QString(output.str().c_str()));
187 }
188 {
189 std::stringstream output;
190 graph.printEdges(output);
191 treeItem->setText(EDGES, QString(output.str().c_str()));
192 }
193 if (times > 0) {
194 treeItem->setText(OCCURRENCE, QString::number(times));
195 } else {
196 treeItem->setText(OCCURRENCE, "none");
197 treeItem->setDisabled(true);
198 }
199 HomologySelection.push_back(treeItem->isSelected());
200
201#ifdef HAVE_QWT
202 // create associated curve in plot
203 CompoundPotential *compound = new CompoundPotential(graph);
204 ASSERT( compound != NULL,
205 "QtHomologyList::refill() - compound is NULL.");
206 TrainingData data(compound->getSpecificFilter());
207 data(homologies.getHomologousGraphs(graph));
208 if (!data.getTrainingInputs().empty()) {
209 // generate QSeisData
210 const TrainingData::InputVector_t &inputs = data.getAllArguments();
211 const TrainingData::OutputVector_t &outputs = data.getTrainingOutputs();
212 std::vector<double> xvalues;
213 std::vector<double> yvalues;
214 for (TrainingData::OutputVector_t::const_iterator outputiter = outputs.begin();
215 outputiter != outputs.end(); ++outputiter)
216 yvalues.push_back((*outputiter)[0]);
217
218 // go through each potential
219 for (CompoundPotential::models_t::const_iterator potiter = compound->begin();
220 potiter != compound->end();
221 ++potiter) {
222 const EmpiricalPotential &potential = dynamic_cast<const EmpiricalPotential &>(**potiter);
223 const std::string potentialname = potential.getName();
224 const FunctionModel::filter_t filter = potential.getSpecificFilter();
225 Coordinator::ptr coordinator = potential.getCoordinator();
226 // then we need to sample the potential
227 xvalues.clear();
228 for (TrainingData::InputVector_t::const_iterator inputiter = inputs.begin();
229 inputiter != inputs.end(); ++inputiter) {
230 const FunctionModel::list_of_arguments_t specificargs = filter(*inputiter);
231 double average = 0.;
232 for (FunctionModel::list_of_arguments_t::const_iterator argiter = specificargs.begin();
233 argiter != specificargs.end(); ++argiter) {
234 const FunctionModel::arguments_t args = *argiter;
235 average += (*coordinator)(args);
236 }
237 if (specificargs.size() > 1) {
238 const size_t index = xvalues.size();
239 xvalues.push_back(average/(double)specificargs.size());
240 yvalues[index] *= 1./(double)specificargs.size();
241 }
242 }
243
244 // We need to sort the xvalues (and associated yvalues also)
245 std::vector<double>::const_iterator xiter = xvalues.begin();
246 std::vector<double>::const_iterator yiter = yvalues.begin();
247 std::map<double, std::set<double> > sorted_xy;
248 for (;xiter != xvalues.end(); ++xiter, ++yiter) {
249 std::set<double> yset;
250 yset.insert(*yiter);
251 std::pair<std::map<double, std::set<double> >::iterator, bool> inserter =
252 sorted_xy.insert(std::make_pair(*xiter, yset));
253 if (!inserter.second)
254 inserter.first->second.insert(*yiter);
255 }
256 xvalues.clear();
257 yvalues.clear();
258 for (std::map<double, std::set<double> >::const_iterator iter = sorted_xy.begin();
259 iter != sorted_xy.end(); ++iter) {
260 for (std::set<double>::const_iterator valueiter = iter->second.begin();
261 valueiter != iter->second.end();
262 ++valueiter) {
263 xvalues.push_back(iter->first);
264 yvalues.push_back(*valueiter);
265 }
266 }
267
268 if ((!xvalues.empty()) && (!yvalues.empty())) {
269 QSeisData data(xvalues, yvalues, QString(potentialname.c_str()));
270 // couple to QSeisPlotCurve and register the curve
271 QSeisPlotCurve *curve = new QSeisPlotCurve(QString(potentialname.c_str()), "energy");
272 curve->updateCurve(&data);
273 if (!QSeisCurveRegistry::getInstance().isPresentByName(curve->getName()))
274 QSeisCurveRegistry::getInstance().registerInstance(curve);
275 else
276 delete curve;
277 // couple to QSeisPlotPage
278 widget->addCurve(potentialname);
279 }
280 }
281 }
282#endif
283 }
284 dirty = false;
285 clearing = false;
286}
287
288void QtHomologyList::paintEvent(QPaintEvent * event)
289{
290 if (dirty)
291 refill();
292// treewidget->paintEvent(event);
293}
294
295void QtHomologyList::subjectKilled(Observable *publisher)
296{
297 // as a new instance should always already be present ... just sign on
298 if (static_cast<PotentialRegistry *>(publisher) == PotentialRegistry::getPointer()) {
299 potentialregistry_enabled = false;
300 } else {
301 // its HomologyContainer
302 }
303}
304
305
306void QtHomologyList::rowSelected()
307{
308 //std::cout << "rowSelected\n";
309 for (int i=0;i<treewidget->topLevelItemCount();i++){
310 QTreeWidgetItem *item = treewidget->topLevelItem(i);
311 bool newSelection = item->isSelected();
312 if (newSelection != HomologySelection[i]){
313 // TODO: Add selected curve to QTabWidget
314 }
315 }
316}
317
Note: See TracBrowser for help on using the repository browser.