From fdd4e505fd5398da11a5e28daf94d0a4d501e16d Mon Sep 17 00:00:00 2001 From: Geoff Hutchison Date: Wed, 18 Dec 2024 23:46:52 -0500 Subject: [PATCH 1/2] Make sure to store electronic and CD spectra Signed-off-by: Geoff Hutchison --- avogadro/quantumio/orca.cpp | 39 +++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/avogadro/quantumio/orca.cpp b/avogadro/quantumio/orca.cpp index c1fe93b398..ae9a5758ef 100644 --- a/avogadro/quantumio/orca.cpp +++ b/avogadro/quantumio/orca.cpp @@ -60,6 +60,23 @@ bool ORCAOutput::read(std::istream& in, Core::Molecule& molecule) return false; } + // this should be the final coordinate set (e.g. the optimized geometry) + molecule.setCoordinate3d(molecule.atomPositions3d(), 0); + if (m_coordSets.size() > 1) { + for (unsigned int i = 0; i < m_coordSets.size(); i++) { + Array positions; + positions.reserve(molecule.atomCount()); + for (size_t j = 0; j < molecule.atomCount(); ++j) { + positions.push_back(m_coordSets[i][j] * BOHR_TO_ANGSTROM); + } + molecule.setCoordinate3d(positions, i + 1); + } + } + + // guess bonds and bond orders + molecule.perceiveBondsSimple(); + molecule.perceiveBondOrders(); + if (m_frequencies.size() > 0 && m_frequencies.size() == m_vibDisplacements.size() && m_frequencies.size() == m_IRintensities.size()) { @@ -98,23 +115,6 @@ bool ORCAOutput::read(std::istream& in, Core::Molecule& molecule) molecule.setSpectra("NMR", nmrData); } - // this should be the final coordinate set (e.g. the optimized geometry) - molecule.setCoordinate3d(molecule.atomPositions3d(), 0); - if (m_coordSets.size() > 1) { - for (unsigned int i = 0; i < m_coordSets.size(); i++) { - Array positions; - positions.reserve(molecule.atomCount()); - for (size_t j = 0; j < molecule.atomCount(); ++j) { - positions.push_back(m_coordSets[i][j] * BOHR_TO_ANGSTROM); - } - molecule.setCoordinate3d(positions, i + 1); - } - } - - // guess bonds and bond orders - molecule.perceiveBondsSimple(); - molecule.perceiveBondOrders(); - // check bonds from calculated bond orders if (m_bondOrders.size() > 0) { for (unsigned int i = 0; i < m_bondOrders.size(); i++) { @@ -251,7 +251,8 @@ void ORCAOutput::processLine(std::istream& in, GaussianSet* basis) getline(in, key); // skip header } // starts at the next line - } else if (Core::contains(key, "CD SPECTRUM")) { + } else if (Core::contains(key, "CD SPECTRUM") && + !Core::contains(key, "TRANSITION VELOCITY DIPOLE")) { m_currentMode = ECD; for (int i = 0; i < 4; ++i) { getline(in, key); // skip header @@ -697,7 +698,7 @@ void ORCAOutput::processLine(std::istream& in, GaussianSet* basis) wavenumbers = Core::lexicalCast(list[1]); // convert to eV - m_electronicTransitions.push_back(wavenumbers / 8065.544); + // m_electronicTransitions.push_back(wavenumbers / 8065.544); m_electronicRotations.push_back(Core::lexicalCast(list[3])); getline(in, key); From 8e4ea5ab7f01d2c97a8a83c51a6dc9eefc111654 Mon Sep 17 00:00:00 2001 From: Geoff Hutchison Date: Wed, 18 Dec 2024 23:47:11 -0500 Subject: [PATCH 2/2] Initial update for electronic and CD spectra plots Signed-off-by: Geoff Hutchison --- avogadro/qtplugins/spectra/spectradialog.cpp | 130 +++++++++++++------ avogadro/qtplugins/spectra/spectradialog.h | 3 + avogadro/qtplugins/spectra/spectradialog.ui | 3 + 3 files changed, 94 insertions(+), 42 deletions(-) diff --git a/avogadro/qtplugins/spectra/spectradialog.cpp b/avogadro/qtplugins/spectra/spectradialog.cpp index 730c4484dc..8da1927b92 100644 --- a/avogadro/qtplugins/spectra/spectradialog.cpp +++ b/avogadro/qtplugins/spectra/spectradialog.cpp @@ -63,6 +63,8 @@ SpectraDialog::SpectraDialog(QWidget* parent) m_ui->dataTable->hide(); m_ui->push_exportData->hide(); + readSettings(); + // connections for options connect(m_ui->push_options, SIGNAL(clicked()), this, SLOT(toggleOptions())); connect(m_ui->push_colorBackground, SIGNAL(clicked()), this, @@ -77,6 +79,17 @@ SpectraDialog::SpectraDialog(QWidget* parent) SLOT(changeFontSize())); connect(m_ui->lineWidthSpinBox, SIGNAL(valueChanged(double)), this, SLOT(changeLineWidth())); + connectOptions(); +} + +SpectraDialog::~SpectraDialog() +{ + writeSettings(); +} + +void SpectraDialog::connectOptions() +{ + // connect (or reconnect) anything that calls change or update plot connect(m_ui->combo_spectra, SIGNAL(currentIndexChanged(int)), this, SLOT(changeSpectra())); connect(m_ui->xAxisMinimum, SIGNAL(valueChanged(double)), this, @@ -89,13 +102,23 @@ SpectraDialog::SpectraDialog(QWidget* parent) SLOT(updatePlot())); connect(m_ui->peakWidth, SIGNAL(valueChanged(double)), this, SLOT(updatePlot())); - - readSettings(); } -SpectraDialog::~SpectraDialog() +void SpectraDialog::disconnectOptions() { - writeSettings(); + // disconnect anything that calls change or update plot + disconnect(m_ui->combo_spectra, SIGNAL(currentIndexChanged(int)), this, + SLOT(changeSpectra())); + disconnect(m_ui->xAxisMinimum, SIGNAL(valueChanged(double)), this, + SLOT(updatePlot())); + disconnect(m_ui->xAxisMaximum, SIGNAL(valueChanged(double)), this, + SLOT(updatePlot())); + disconnect(m_ui->yAxisMinimum, SIGNAL(valueChanged(double)), this, + SLOT(updatePlot())); + disconnect(m_ui->yAxisMaximum, SIGNAL(valueChanged(double)), this, + SLOT(updatePlot())); + disconnect(m_ui->peakWidth, SIGNAL(valueChanged(double)), this, + SLOT(updatePlot())); } void SpectraDialog::changeSpectra() @@ -103,6 +126,8 @@ void SpectraDialog::changeSpectra() // TODO: change the scale and offset based on defaults and settings QSettings settings; + disconnectOptions(); + // what type of spectra are we plotting? SpectraType type = static_cast(m_ui->combo_spectra->currentData().toInt()); @@ -154,38 +179,8 @@ void SpectraDialog::changeSpectra() break; } - MatrixX& spectra = - m_spectra[m_ui->combo_spectra->currentText().toStdString()]; - float maxIntensity = 1.0; - // update the data table - m_ui->dataTable->setRowCount(spectra.rows()); - m_ui->dataTable->setColumnCount(spectra.cols()); - for (auto i = 0; i < spectra.rows(); ++i) { - for (auto j = 0; j < spectra.cols(); ++j) { - QTableWidgetItem* item = - new QTableWidgetItem(QString::number(spectra(i, j), 'f', 4)); - m_ui->dataTable->setItem(i, j, item); - } - } - // if there's a second column, check for intensities - if (spectra.cols() > 1) { - for (auto i = 0; i < spectra.rows(); ++i) { - if (spectra(i, 1) > maxIntensity) - maxIntensity = spectra(i, 1); - } - maxIntensity = maxIntensity * 1.25; - } - // if transmission for IR, set the max intensity to 100 - if (type == SpectraType::Infrared) - maxIntensity = 100.0; - - if (maxIntensity < 1.0) - maxIntensity = 1.0; - - // update the spin box - m_ui->yAxisMaximum->setValue(maxIntensity); - updatePlot(); + connectOptions(); } void SpectraDialog::setSpectra(const std::map& spectra) @@ -193,9 +188,13 @@ void SpectraDialog::setSpectra(const std::map& spectra) m_spectra = spectra; // update the combo box + disconnect(m_ui->combo_spectra, SIGNAL(currentIndexChanged(int)), this, + SLOT(changeSpectra())); + m_ui->combo_spectra->clear(); for (auto& spectra : m_spectra) { QString name = QString::fromStdString(spectra.first); + if (name == "IR") { name = tr("Infrared"); m_ui->combo_spectra->addItem(name, @@ -222,7 +221,9 @@ void SpectraDialog::setSpectra(const std::map& spectra) } changeSpectra(); - updatePlot(); + // connect again + connect(m_ui->combo_spectra, SIGNAL(currentIndexChanged(int)), this, + SLOT(changeSpectra())); } void SpectraDialog::writeSettings() const @@ -319,6 +320,9 @@ void SpectraDialog::changeLineWidth() void SpectraDialog::updatePlot() { + // disconnect the options while we update the plot + disconnectOptions(); + // the raw data std::vector transitions, intensities; // for the plot @@ -392,7 +396,11 @@ void SpectraDialog::updatePlot() break; case SpectraType::CircularDichroism: transitions = fromMatrix(m_spectra["Electronic"].col(0)); - intensities = fromMatrix(m_spectra["Electronic"].col(2)); + // check if electronic has a third column + if (m_spectra["Electronic"].cols() > 2) + intensities = fromMatrix(m_spectra["Electronic"].col(2)); + else // grab it from the CD data + intensities = fromMatrix(m_spectra["CircularDichroism"].col(1)); windowName = tr("Circular Dichroism Spectra"); xTitle = tr("eV)"); yTitle = tr("Intensity"); @@ -419,12 +427,41 @@ void SpectraDialog::updatePlot() } setWindowTitle(windowName); + // update the data table + m_ui->dataTable->setRowCount(transitions.size()); + m_ui->dataTable->setColumnCount(2); + for (auto i = 0; i < transitions.size(); ++i) { + // frequency or energy + QTableWidgetItem* item = + new QTableWidgetItem(QString::number(transitions[i], 'f', 4)); + m_ui->dataTable->setItem(i, 0, item); + // intensities + item = new QTableWidgetItem(QString::number(intensities[i], 'f', 4)); + m_ui->dataTable->setItem(i, 1, item); + } + double maxIntensity = 0.0f; for (auto intensity : intensities) { if (intensity > maxIntensity) maxIntensity = intensity; } + // if transmission for IR, set the max intensity to 100 + if (type == SpectraType::Infrared) + maxIntensity = 100.0; + + if (maxIntensity < 1.0) + maxIntensity = 1.0; + + // update the spin boxes + m_ui->yAxisMaximum->setValue(maxIntensity); + m_ui->yAxisMinimum->setMinimum(0.0); + // if CD, set the minimum too + if (type == SpectraType::CircularDichroism) { + m_ui->yAxisMinimum->setMinimum(-maxIntensity * 2.0); + m_ui->yAxisMinimum->setValue(-maxIntensity); + } + // now compose the plot data float scale = m_ui->scaleSpinBox->value(); float offset = m_ui->offsetSpinBox->value(); @@ -433,11 +470,17 @@ void SpectraDialog::updatePlot() float xMin = m_ui->xAxisMinimum->value(); float xMax = m_ui->xAxisMaximum->value(); - int start = std::min(static_cast(xMin), static_cast(xMax)); - int end = std::max(static_cast(xMin), static_cast(xMax)); + float start = std::min(xMin, xMax); + float end = std::max(xMin, xMax); + // for some spectra, we need to take small steps, so we scale the x axis + float xScale = 1.0; + if (type == SpectraType::Electronic || type == SpectraType::CircularDichroism) + xScale = 1.0f / 0.05f; + + float stickWidth = fwhm / (xScale * 30.0); - for (unsigned int x = start; x < end; ++x) { - float xValue = static_cast(x); + for (unsigned int x = round(start * xScale); x < round(end * xScale); ++x) { + float xValue = static_cast(x) / xScale; xData.push_back(xValue); yData.push_back(0.0f); yStick.push_back(0.0f); @@ -448,7 +491,7 @@ void SpectraDialog::updatePlot() float peak = intensities[index]; float intensity = scaleAndBlur(xValue, freq, peak, scale, offset, fwhm); - float stick = scaleAndBlur(xValue, freq, peak, scale, offset, 1.0); + float stick = scaleAndBlur(xValue, freq, peak, scale, offset, stickWidth); yData.back() += intensity; yStick.back() += stick; @@ -492,6 +535,9 @@ void SpectraDialog::updatePlot() chart->setXAxisLimits(xAxisMin, xAxisMax); chart->setYAxisLimits(yAxisMin, yAxisMax); + + // re-enable the options + connectOptions(); } VTK::ChartWidget* SpectraDialog::chartWidget() diff --git a/avogadro/qtplugins/spectra/spectradialog.h b/avogadro/qtplugins/spectra/spectradialog.h index 4b96a74a4a..db00eee1f4 100644 --- a/avogadro/qtplugins/spectra/spectradialog.h +++ b/avogadro/qtplugins/spectra/spectradialog.h @@ -48,6 +48,9 @@ class SpectraDialog : public QDialog VTK::ChartWidget* chartWidget(); + void disconnectOptions(); + void connectOptions(); + private slots: void changeBackgroundColor(); void changeForegroundColor(); diff --git a/avogadro/qtplugins/spectra/spectradialog.ui b/avogadro/qtplugins/spectra/spectradialog.ui index 2d0574af20..16125c45a7 100644 --- a/avogadro/qtplugins/spectra/spectradialog.ui +++ b/avogadro/qtplugins/spectra/spectradialog.ui @@ -80,6 +80,9 @@ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + -4000.000000000000000 + 4000.000000000000000