Skip to content

Commit

Permalink
Initial vibrational spectra plot
Browse files Browse the repository at this point in the history
- Needs spectral broadening
- Needs to be general for other spectra
- ChartDialog needs more methods

Signed-off-by: Geoff Hutchison <[email protected]>
  • Loading branch information
ghutchis committed Oct 30, 2023
1 parent bcf2b3d commit 39ba7df
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 4 deletions.
2 changes: 2 additions & 0 deletions avogadro/qtplugins/spectra/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ avogadro_plugin(Spectra
"${plugin_srcs}"
"vibrationdialog.ui"
)

target_link_libraries(Spectra PRIVATE Avogadro::Vtk)
59 changes: 59 additions & 0 deletions avogadro/qtplugins/spectra/spectra.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#include <avogadro/core/vector.h>
#include <avogadro/qtgui/molecule.h>

#include <avogadro/vtk/chartdialog.h>
#include <avogadro/vtk/chartwidget.h>

#include <QAction>
#include <QDebug>
#include <QtCore/QTimer>
Expand All @@ -27,6 +30,12 @@ Spectra::Spectra(QObject* p)
action->setText(tr("Vibrational Modes…"));
connect(action, SIGNAL(triggered()), SLOT(openDialog()));
m_actions.push_back(action);

action = new QAction(this);
action->setEnabled(false);
action->setText(tr("Spectra…"));
connect(action, SIGNAL(triggered()), SLOT(showSpectraChart()));
m_actions.push_back(action);
}

Spectra::~Spectra() {}
Expand All @@ -50,6 +59,7 @@ void Spectra::setMolecule(QtGui::Molecule* mol)
isVibrational = true;

m_actions[0]->setEnabled(isVibrational);
m_actions[1]->setEnabled(isVibrational);
m_molecule = mol;
if (m_dialog)
m_dialog->setMolecule(mol);
Expand Down Expand Up @@ -212,6 +222,55 @@ void Spectra::openDialog()
m_dialog->show();
}

void Spectra::showSpectraChart()
{
if (m_molecule == nullptr || m_molecule->vibrationFrequencies().empty())
return;

std::vector<float> xData;
std::vector<float> yData;
// generate the raw stick spectrum
float maxIntensity = 0.0f;
for (unsigned int x = 0; x < 4000; ++x) {
xData.push_back(static_cast<float>(x));
// check if x is near a frequency and add a peak
bool found = false;
for (auto index = 0; index < m_molecule->vibrationFrequencies().size();
++index) {
auto freq = m_molecule->vibrationFrequencies()[index];
if (std::abs(static_cast<int>(x) - static_cast<int>(freq)) < 2) {
yData.push_back(m_molecule->vibrationIRIntensities()[index]);
if (m_molecule->vibrationIRIntensities()[index] > maxIntensity)
maxIntensity = m_molecule->vibrationIRIntensities()[index];

found = true;
break;
}
}
if (!found)
yData.push_back(0.0f);
}

auto xTitle = tr("Wavenumbers (cm⁻¹)");
auto yTitle = tr("Transmission");
auto windowName = tr("Vibrational Spectra");

if (!m_chartDialog) {
m_chartDialog.reset(
new VTK::ChartDialog(qobject_cast<QWidget*>(this->parent())));
}

m_chartDialog->setWindowTitle(windowName);
auto* chart = m_chartDialog->chartWidget();
chart->clearPlots();
chart->setXAxisTitle(xTitle.toStdString());
chart->setYAxisTitle(yTitle.toStdString());
chart->addPlot(xData, yData, VTK::color4ub{ 255, 0, 0, 255 });
chart->setXAxisLimits(4000.0, 0.0);
chart->setYAxisLimits(maxIntensity, 0.0);
m_chartDialog->show();
}

void Spectra::advanceFrame()
{
if (++m_currentFrame >= m_totalFrames)
Expand Down
7 changes: 7 additions & 0 deletions avogadro/qtplugins/spectra/spectra.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ class QDialog;
class QTimer;

namespace Avogadro {

namespace VTK {
class ChartDialog;
}

namespace QtPlugins {

class VibrationDialog;
Expand Down Expand Up @@ -53,6 +58,7 @@ public slots:
void startVibrationAnimation();
void stopVibrationAnimation();
void openDialog();
void showSpectraChart();

private slots:
void advanceFrame();
Expand All @@ -63,6 +69,7 @@ private slots:
QtGui::Molecule* m_molecule;

VibrationDialog* m_dialog;
QScopedPointer<VTK::ChartDialog> m_chartDialog;

QTimer* m_timer;

Expand Down
36 changes: 34 additions & 2 deletions avogadro/vtk/chartwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <vtkRenderWindow.h>
#include <vtkStringArray.h>
#include <vtkTable.h>
#include <vtkTextProperty.h>

#include <QHBoxLayout>

Expand Down Expand Up @@ -113,16 +114,26 @@ void ChartWidget::clearPlots()
m_table->RemoveAllColumns();
}

void ChartWidget::setXAxisTitle(const char* title)
void ChartWidget::setXAxisTitle(const std::string title)

Check warning on line 117 in avogadro/vtk/chartwidget.cpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

avogadro/vtk/chartwidget.cpp#L117

Function parameter 'title' should be passed by const reference.
{
auto* axis = m_chart->GetAxis(vtkAxis::BOTTOM);
axis->SetTitle(title);
axis->SetTitleVisible(true);
axis->GetTitleProperties()->SetFontSize(18);
axis->GetTitleProperties()->SetBold(true);

axis->GetLabelProperties()->SetFontSize(14);
}

void ChartWidget::setYAxisTitle(const char* title)
void ChartWidget::setYAxisTitle(const std::string title)

Check warning on line 128 in avogadro/vtk/chartwidget.cpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

avogadro/vtk/chartwidget.cpp#L128

Function parameter 'title' should be passed by const reference.
{
auto* axis = m_chart->GetAxis(vtkAxis::LEFT);
axis->SetTitle(title);
axis->SetTitleVisible(true);
axis->GetTitleProperties()->SetFontSize(18);
axis->GetTitleProperties()->SetBold(true);

axis->GetLabelProperties()->SetFontSize(14);
}

void ChartWidget::setTickLabels(Axis a, const std::vector<float>& tickPositions,
Expand Down Expand Up @@ -161,6 +172,27 @@ void ChartWidget::setAxisLimits(Axis a, float min, float max)
customAxis->SetBehavior(vtkAxis::FIXED);
}

void ChartWidget::setXAxisLimits(float min, float max)
{
setAxisLimits(Axis::x, min, max);
}

void ChartWidget::setYAxisLimits(float min, float max)
{
setAxisLimits(Axis::y, min, max);
}

void ChartWidget::setAxisLogScale(Axis a, bool logScale)
{
auto customAxis = axis(a);

// We need a valid axis and equal sizes vectors of points/labels.
if (!customAxis)
return;

customAxis->SetLogScale(logScale);
}

vtkAxis* ChartWidget::axis(Axis a)
{
if (a == Axis::x)
Expand Down
10 changes: 8 additions & 2 deletions avogadro/vtk/chartwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
#include "avogadrovtkexport.h"

#include <QWidget>

#include <array>
#include <string>

#include <vtkNew.h>

Expand Down Expand Up @@ -43,14 +45,18 @@ class AVOGADROVTK_EXPORT ChartWidget : public QWidget

void clearPlots();

void setXAxisTitle(const char* title);
void setXAxisTitle(const std::string title);

Check warning on line 48 in avogadro/vtk/chartwidget.h

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

avogadro/vtk/chartwidget.h#L48

Function parameter 'title' should be passed by const reference.

void setYAxisTitle(const char* title);
void setYAxisTitle(const std::string title);

Check warning on line 50 in avogadro/vtk/chartwidget.h

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

avogadro/vtk/chartwidget.h#L50

Function parameter 'title' should be passed by const reference.

void setTickLabels(Axis a, const std::vector<float>& tickPositions,
const std::vector<std::string>& tickLabels);

void setAxisLimits(Axis a, float min, float max);
void setXAxisLimits(float min, float max);
void setYAxisLimits(float min, float max);

void setAxisLogScale(Axis a, bool logScale);

private:
void renderViews();
Expand Down

0 comments on commit 39ba7df

Please sign in to comment.