Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support more molecular properties #1822

Merged
merged 3 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions avogadro/qtplugins/applycolors/applycolors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@
#include <avogadro/core/vector.h>
#include <avogadro/qtgui/molecule.h>

#include <QStringList>
#include <QAction>
#include <QColorDialog>
#include <QInputDialog>
#include <QStringList>

#include <QDebug>

using namespace tinycolormap;

Expand Down Expand Up @@ -248,14 +250,14 @@ void ApplyColors::applyChargeColors()

// populate the dialog to choose the model and colormap
ChargeColorDialog dialog;
for (const auto &model : identifiers) {
for (const auto& model : identifiers) {
auto name = Calc::ChargeManager::instance().nameForModel(model);
dialog.modelCombo->addItem(name.c_str(), model.c_str());
}
dialog.exec();
if (dialog.result() != QDialog::Accepted)
return;

// get the model and colormap
const auto model = dialog.modelCombo->currentData().toString().toStdString();
const auto colormapName = dialog.colorMapCombo->currentText();
Expand All @@ -267,6 +269,12 @@ void ApplyColors::applyChargeColors()
float maxCharge = 0.0f;
auto charges =
Calc::ChargeManager::instance().partialCharges(model, *m_molecule);
// check if the model string is already a partial charge type
if (m_molecule->partialChargeTypes().find(model) !=
m_molecule->partialChargeTypes().end()) {
charges = m_molecule->partialCharges(model);
}

for (Index i = 0; i < numAtoms; ++i) {
float charge = charges(i, 0);
minCharge = std::min(minCharge, charge);
Expand Down Expand Up @@ -568,4 +576,4 @@ void ApplyColors::applyShapelyColors()
m_molecule->emitChanged(QtGui::Molecule::Atoms);
}

} // namespace Avogadro
} // namespace Avogadro::QtPlugins
14 changes: 14 additions & 0 deletions avogadro/qtplugins/molecularproperties/molecularmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,16 @@ QString formatFormula(Molecule* molecule)
return formula;
}

QString formatPointGroup(std::string pointgroup)
{
// first character is in capital
// then everything else is in subscript using <sub>...</sub>
QString formatted = QString::fromStdString(pointgroup);
QString output = formatted.at(0).toUpper();
output += QString("<sub>%1</sub>").arg(formatted.mid(1));
return output;
}

// Qt calls this for multiple "roles" across row / columns in the index
// we also combine multiple types into this class, so lots of special cases
QVariant MolecularModel::data(const QModelIndex& index, int role) const
Expand Down Expand Up @@ -247,6 +257,8 @@ QVariant MolecularModel::data(const QModelIndex& index, int role) const
else if (key == " 9totalSpinMultiplicity")
return QVariant::fromValue(
static_cast<int>(m_molecule->totalSpinMultiplicity()));
else if (key == "pointgroup")
return formatPointGroup(it->second.toString());

return QString::fromStdString(it->second.toString());
}
Expand Down Expand Up @@ -317,6 +329,8 @@ QVariant MolecularModel::headerData(int section, Qt::Orientation orientation,
return tr("Entropy (kcal/mol•K)");
else if (it->first == "gibbs")
return tr("Gibbs Free Energy (kcal/mol)");
else if (it->first == "pointgroup")
return tr("Point Group", "point group symmetry");
else if (it != map.end())
return QString::fromStdString(it->first);

Expand Down
1 change: 1 addition & 0 deletions avogadro/qtplugins/symmetry/symmetrywidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ void SymmetryWidget::setCenterOfMass(double cm[3])
void SymmetryWidget::setPointGroupSymbol(QString pg)
{
m_ui->pointGroupLabel->setText(pg);
m_molecule->setData("pointgroup", pg.toStdString());
}

void SymmetryWidget::setSymmetryOperations(
Expand Down
52 changes: 44 additions & 8 deletions avogadro/quantumio/orca.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,6 @@ bool ORCAOutput::read(std::istream& in, Core::Molecule& molecule)
return false;
}

// add the partial charges
if (m_partialCharges.size() > 0) {
for (auto it = m_partialCharges.begin(); it != m_partialCharges.end();
++it) {
molecule.setPartialCharges(it->first, it->second);
}
}

if (m_frequencies.size() > 0 &&
m_frequencies.size() == m_vibDisplacements.size() &&
m_frequencies.size() == m_IRintensities.size()) {
Expand Down Expand Up @@ -143,6 +135,17 @@ bool ORCAOutput::read(std::istream& in, Core::Molecule& molecule)
basis->setMolecule(&molecule);
load(basis);

// we have to do a few things *after* any modifications to bonds / atoms
// because those automatically clear partial charges and data

// add the partial charges
if (m_partialCharges.size() > 0) {
for (auto it = m_partialCharges.begin(); it != m_partialCharges.end();
++it) {
molecule.setPartialCharges(it->first, it->second);
}
}

molecule.setData("totalCharge", m_charge);
molecule.setData("totalSpinMultiplicity", m_spin);
molecule.setData("dipoleMoment", m_dipoleMoment);
Expand Down Expand Up @@ -273,6 +276,11 @@ void ORCAOutput::processLine(std::istream& in, GaussianSet* basis)
} else if (Core::contains(key, "MOLECULAR ORBITALS")) {
m_currentMode = MO;
getline(in, key); //------------
} else if (Core::contains(key, "HIRSHFELD ANALYSIS")) {
m_currentMode = HirshfeldCharges;
for (unsigned int i = 0; i < 6; ++i) {
getline(in, key); // skip header
}
} else if (Core::contains(key, "ATOMIC CHARGES")) {
m_currentMode = Charges;
// figure out what type of charges we have
Expand Down Expand Up @@ -352,6 +360,34 @@ void ORCAOutput::processLine(std::istream& in, GaussianSet* basis)
m_currentMode = NotParsing;
break;
}
case HirshfeldCharges: {
// should start at the first atom
if (key.empty())
break;

Eigen::MatrixXd charges(m_atomNums.size(), 1);
charges.setZero();

list = Core::split(key, ' ');
while (!key.empty()) {
if (list.size() != 4) {
break;
}
// e.g. index atom charge spin
// e.g. 0 O -0.714286 0.000
int atomIndex = Core::lexicalCast<int>(list[0]);
double charge = Core::lexicalCast<double>(list[2]);
charges(atomIndex, 0) = charge;

getline(in, key);
key = Core::trimmed(key);
list = Core::split(key, ' ');
}

m_partialCharges["Hirshfeld"] = charges;
m_currentMode = NotParsing;
break;
}
case Charges: {
// should start at the first atom
if (key.empty())
Expand Down
1 change: 1 addition & 0 deletions avogadro/quantumio/orca.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class AVOGADROQUANTUMIO_EXPORT ORCAOutput : public Io::FileFormat
MO,
OrbitalEnergies,
Charges,
HirshfeldCharges,
Frequencies,
VibrationalModes,
IR,
Expand Down
Loading