I examined the issue and concluded that it is necessary to manipulate the vibration widget for vibration display.
Pointer variables to components of the vibration widget can be retrieved as follows:
QWidget* vibrationDock;
QWidget* vibrationWidget;
QTableWidget* vibrationTable;
QPushButton* spectraButton;
QCheckBox* displayForcesCheckBox;
QPushButton* animationButton;
QPushButton* pauseButton;
foreach (QWidget *widget, QApplication::allWidgets())
{
if (widget->objectName().contains("vibrationDock",Qt::CaseInsensitive))
vibrationDock = widget;
vibrationWidget = vibrationDock->findChild<QWidget*>("VibrationWidget");
vibrationTable = vibrationDock->findChild<QTableWidget*>("vibrationTable");
spectraButton = vibrationDock->findChild<QPushButton*>("spectraButton");
displayForcesCheckBox = vibrationDock->findChild<QCheckBox*>("displayForcesCheckBox");
animationButton = vibrationDock->findChild<QPushButton*>("animationButton");
pauseButton = vibrationDock->findChild<QPushButton*>("pauseButton");
}
Some operations are necessary beforehand.
// Show the vibration dock if it is hidden
if (!vibrationDock->isVisible())
vibrationDock->show();
// Activate the vibration widget
vibrationWidget->setEnabled(true);
// Activate animation buttons
animationButton->setEnabled(true);
pauseButton->setEnabled(true);
// Disconnect SIGNAL/SLOTs to avoid exception when a component is clicked.
spectraButton->disconnect();
displayForcesCheckBox->disconnect();
animationButton->disconnect();
pauseButton->disconnect();
Set frequencis and intensities stored in vectors vF and vI on the vibration table.
(vF and vI were defined in the previous post.)
vibrationTable->horizontalHeader()->show();
vibrationTable->setColumnCount(2);
vibrationTable->setRowCount(vF.size());
for (unsigned int row = 0; row < vF.size(); ++row)
{
char buf[64];
sprintf(buf, "%lf", vF[row]);
QString Freq(buf);
sprintf(buf, "%lf", vI[row]);
QString Int(buf);
QTableWidgetItem* newFreq = new QTableWidgetItem;
newFreq->setText(Freq);
QTableWidgetItem* newInten = new QTableWidgetItem;
newInten->setText(Int);
vibrationTable->setItem(row, 0, newFreq);
vibrationTable->setItem(row, 1, newInten);
}
Create vibration animation for a selected mode.
Animation* m_animation = new Animation;
unsigned int m_framesPerStep = 8; // Frame number per a vibration motion.
qreal m_vibScale = 0.7; // Vibration amplitude scale factor
// Number of atoms consists in Avogadro::Molecule* m_molecule
unsigned int nAtoms = m_molecule->numAtoms();
// Atom list consists in Avogadro::Molecule* m_molecule
QList<Atom *> atoms = m_molecule->atoms();
m_molecule->setConformer(0);
std::vector<std::vector<Eigen::Vector3d> *> m_curFrames; // Conformers representing frames for a vibration
for(int i = 0; i< m_framesPerStep ; i++ )
m_curFrames.push_back(new std::vector<Eigen::Vector3d>(nAtoms));
vibrationTable->setCurrentCell(0,0); // Select a cell (a row, a column)
int curRow = vibrationTable->currentRow();
// This selects always 0th row.
// It needs use of SIGNAL/SLOT for dynamic row (or mode) selection.
for(int i = 0; i< m_framesPerStep ; i++ )
{
for(int j=0; j<nAtoms; j++)
{
m_curFrames.at(i)->at(j).x() = atoms.at(j)->pos()->x() + vLx.at(curRow).at(j).x() * m_vibScale * sin(2*M_PI*i/(m_framesPerStep-1));
m_curFrames.at(i)->at(j).y() = atoms.at(j)->pos()->y() + vLx.at(curRow).at(j).y() * m_vibScale * sin(2*M_PI*i/(m_framesPerStep-1));
m_curFrames.at(i)->at(j).z() = atoms.at(j)->pos()->z() + vLx.at(curRow).at(j).z() * m_vibScale * sin(2*M_PI*i/(m_framesPerStep-1));
}
}
m_animation->setFrame(1); // Set the current frame
m_animation->setFps(10);
m_animation->setLoopCount(0); // argument 0 means "repeat forever".
m_animation->setFrames(m_curFrames);
m_animation->setMolecule(m_molecule);
connect(animationButton, SIGNAL(clicked()), m_animation, SLOT(start()) );
connect(pauseButton, SIGNAL(clicked()), m_animation, SLOT(pause()) );
Plot IR spectrum with vectors vF and vI which defined as in the previous post.
SpectraPlotDialog *m_dialog = new SpectraPlotDialog(qobject_cast<QWidget*>(parent()));
if (m_molecule)
m_dialog->setIRSpectra(m_molecule, vF, vI);
connect( spectraButton, SIGNAL(clicked()), m_dialog, SLOT(show()) );
Oops, New class SpectraPlotDialog must be defined in advance.
I defined it as a same manner of the example, “libavogadro/examples/thirdPartyExtensions/05-ConformerPlot/”.
#include "ui_spectraplotdialog.h"
class SpectraPlotDialog : public QDialog
{
Q_OBJECT
public:
explicit SpectraPlotDialog(QWidget *parent = 0, Qt::WindowFlags f = 0 );
virtual ~SpectraPlotDialog(){}
public slots:
void setIRSpectra(Molecule *mol, std::vector< double > vF, std::vector< double > vI);
private:
Ui::SpectraPlotDialog ui;
Molecule *m_molecule;
};
SpectraPlotDialog::SpectraPlotDialog(QWidget *parent, Qt::WindowFlags f )
: QDialog( parent, f )
{ ui.setupUi(this); }
void SpectraPlotDialog::setIRSpectra(Molecule *mol, std::vector< double > vF, std::vector< double > vI)
{
ui.plot->resetPlot();
m_molecule = mol;
if (!m_molecule) return;
PlotObject *data = new PlotObject (Qt::red, // the color for the plotting object
PlotObject::Bars, // Plotting object. Points, Lines or Bars
2);
for(int i = 0; i< vF.size() ; i++)
{ data->addPoint( vF.at(i), vI.at(i), QString::number(vF.at(i)), 1.0); }
ui.plot->setDefaultLimits(500,
3500,
0.0,
0.01);
ui.plot->setAntialiasing(true);
ui.plot->setMouseTracking(true);
ui.plot->axis(PlotWidget::BottomAxis)->setLabel(tr("Wavenumber(cm-1)"));
ui.plot->axis(PlotWidget::LeftAxis)->setLabel(tr("Intensity (km/mol)"));
ui.plot->addPlotObject(data);
}
spectraplotdialog.ui is ( almost identical to
libavogadro/examples/thirdPartyExtensions/05-ConformerPlot/conformerplotdialog.ui):
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SpectraPlotDialog</class>
<widget class="QDialog" name="SpectraPlotDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>908</width>
<height>453</height>
</rect>
</property>
<property name="windowTitle">
<string>Spetrum Plot</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="Avogadro::PlotWidget" name="plot">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Avogadro::PlotWidget</class>
<extends>QFrame</extends>
<header location="global">avogadro/plotwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
Although there are some problems such as no association with check boxes and the amplitude slider,IR spectrum lines have no band width and turn upward etc., basic functionality was impremented in this code.
Thank you.