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

Check for Open Babel CJSON support: use it if available #937

Merged
merged 1 commit into from
Jun 10, 2022
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
73 changes: 39 additions & 34 deletions avogadro/qtplugins/openbabel/obfileformat.cpp
Original file line number Diff line number Diff line change
@@ -1,29 +1,16 @@
/******************************************************************************

This source file is part of the Avogadro project.

Copyright 2013 Kitware, Inc.

This source code is released under the New BSD License, (the "License").

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

This source code is released under the 3-Clause BSD License, (see "LICENSE").
******************************************************************************/

#include "obfileformat.h"

#include "obprocess.h"

#include <avogadro/io/cmlformat.h>
#include <avogadro/io/pdbformat.h>

#include <nlohmann/json.hpp>

#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QFileInfo>
#include <QtCore/QTimer>

Expand Down Expand Up @@ -81,11 +68,12 @@ OBFileFormat::OBFileFormat(const std::string& name_,
const std::string& specificationUrl_,
const std::vector<std::string> fileExtensions_,
const std::vector<std::string> mimeTypes_,
bool fileOnly_)
const std::string& defaultFormat_, bool fileOnly_)
: Io::FileFormat(), m_description(description_),
m_fileExtensions(fileExtensions_), m_mimeTypes(mimeTypes_),
m_identifier(identifier_), m_name(name_),
m_specificationUrl(specificationUrl_), m_fileOnly(fileOnly_)
m_specificationUrl(specificationUrl_), m_defaultFormat(defaultFormat_),
m_fileOnly(fileOnly_)
{}

OBFileFormat::~OBFileFormat() {}
Expand Down Expand Up @@ -132,8 +120,10 @@ bool OBFileFormat::read(std::istream& in, Core::Molecule& molecule)
}

// check if we're going to read to a different format
// default is CML
QString format = QString::fromStdString(opts.value("format", "cml"));
// default is CML or CJSON
QString format =
QString::fromStdString(opts.value("format", m_defaultFormat));
qDebug() << "Reading to format: " << format << m_defaultFormat.c_str();

if (!m_fileOnly) {
// Determine length of data
Expand Down Expand Up @@ -187,17 +177,22 @@ bool OBFileFormat::read(std::istream& in, Core::Molecule& molecule)
}

if (format == "cml") {
Io::CmlFormat cmlReader;
if (!cmlReader.readString(std::string(output.constData()), molecule)) {
if (!m_cmlFormat.readString(std::string(output.constData()), molecule)) {
appendError(std::string("Error while reading OpenBabel-generated CML:"));
appendError(cmlReader.error());
appendError(m_cmlFormat.error());
return false;
}
} else if (format == "cjson") {
if (!m_cjsonFormat.readString(std::string(output.constData()), molecule)) {
appendError(
std::string("Error while reading OpenBabel-generated CJSON:"));
appendError(m_cjsonFormat.error());
return false;
}
} else if (format == "pdb") {
Io::PdbFormat pdbReader;
if (!pdbReader.readString(std::string(output.constData()), molecule)) {
if (!m_pdbFormat.readString(std::string(output.constData()), molecule)) {
appendError(std::string("Error while reading OpenBabel-generated PDB:"));
appendError(pdbReader.error());
appendError(m_pdbFormat.error());
return false;
}
} else {
Expand Down Expand Up @@ -225,13 +220,22 @@ bool OBFileFormat::write(std::ostream& out, const Core::Molecule& molecule)
}
}

// Generate CML to give to OpenBabel
std::string cml;
Io::CmlFormat cmlWriter;
if (!cmlWriter.writeString(cml, molecule)) {
appendError(std::string("Error while writing CML:"));
appendError(cmlWriter.error());
return false;
qDebug() << " writing to " << m_defaultFormat.c_str();

// Generate CML or CJSON to give to OpenBabel
std::string outputString;
if (m_defaultFormat == "cml") {
if (!m_cmlFormat.writeString(outputString, molecule)) {
appendError(std::string("Error while writing CML:"));
appendError(m_cmlFormat.error());
return false;
}
} else if (m_defaultFormat == "cjson") {
if (!m_cjsonFormat.writeString(outputString, molecule)) {
appendError(std::string("Error while writing CJSON:"));
appendError(m_cjsonFormat.error());
return false;
}
}

// Block until the OpenBabel conversion finishes:
Expand All @@ -246,7 +250,8 @@ bool OBFileFormat::write(std::ostream& out, const Core::Molecule& molecule)
appendError("Internal error: No file extensions set.");
return false;
}
proc.convert(QByteArray(cml.c_str()), "cml",

proc.convert(QByteArray(outputString.c_str()), m_defaultFormat.c_str(),
QString::fromStdString(m_fileExtensions.front()), options);

QByteArray output;
Expand Down Expand Up @@ -274,7 +279,7 @@ Io::FileFormat* OBFileFormat::newInstance() const
{
return new OBFileFormat(m_name, m_identifier, m_description,
m_specificationUrl, m_fileExtensions, m_mimeTypes,
m_fileOnly);
m_defaultFormat, m_fileOnly);
}

} // namespace QtPlugins
Expand Down
24 changes: 12 additions & 12 deletions avogadro/qtplugins/openbabel/obfileformat.h
Original file line number Diff line number Diff line change
@@ -1,24 +1,17 @@
/******************************************************************************

This source file is part of the Avogadro project.

Copyright 2013 Kitware, Inc.

This source code is released under the New BSD License, (the "License").

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

This source code is released under the 3-Clause BSD License, (see "LICENSE").
******************************************************************************/

#ifndef AVOGADRO_QTPLUGINS_OBFILEFORMAT_H
#define AVOGADRO_QTPLUGINS_OBFILEFORMAT_H

#include <avogadro/io/fileformat.h>

#include <avogadro/io/cjsonformat.h>
#include <avogadro/io/cmlformat.h>
#include <avogadro/io/pdbformat.h>

namespace Avogadro {
namespace QtPlugins {

Expand All @@ -34,6 +27,7 @@ class OBFileFormat : public Avogadro::Io::FileFormat
const std::string& specificationUrl_,
const std::vector<std::string> fileExtensions_,
const std::vector<std::string> mimeTypes_,
const std::string& defaultFormat_,
bool fileOnly_ = false);
~OBFileFormat() override;

Expand Down Expand Up @@ -81,7 +75,13 @@ class OBFileFormat : public Avogadro::Io::FileFormat
std::string m_identifier;
std::string m_name;
std::string m_specificationUrl;
std::string m_defaultFormat;
bool m_fileOnly;

// internal format objects for interchange with obabel
Io::CjsonFormat m_cjsonFormat;
Io::CmlFormat m_cmlFormat;
Io::PdbFormat m_pdbFormat;
};

} // namespace QtPlugins
Expand Down
13 changes: 1 addition & 12 deletions avogadro/qtplugins/openbabel/obforcefielddialog.cpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,6 @@
/******************************************************************************

This source file is part of the Avogadro project.

Copyright 2013 Kitware, Inc.

This source code is released under the New BSD License, (the "License").

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

This source code is released under the 3-Clause BSD License, (see "LICENSE").
******************************************************************************/

#include "obforcefielddialog.h"
Expand Down
13 changes: 1 addition & 12 deletions avogadro/qtplugins/openbabel/obforcefielddialog.h
Original file line number Diff line number Diff line change
@@ -1,17 +1,6 @@
/******************************************************************************

This source file is part of the Avogadro project.

Copyright 2013 Kitware, Inc.

This source code is released under the New BSD License, (the "License").

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

This source code is released under the 3-Clause BSD License, (see "LICENSE").
******************************************************************************/

#ifndef AVOGADRO_QTPLUGINS_OBFORCEFIELDDIALOG_H
Expand Down
14 changes: 10 additions & 4 deletions avogadro/qtplugins/openbabel/obprocess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,17 +325,23 @@ void OBProcess::queryChargesPrepare()
}

bool OBProcess::optimizeGeometry(const QByteArray& mol,
const QStringList& options)
const QStringList& options,
const std::string format)
{
if (!tryLockProcess()) {
qWarning() << "OBProcess::optimizeGeometry(): process already in use.";
return false;
}

QStringList realOptions;
realOptions << "-icml"
<< "-ocml"
<< "--minimize"
if (format == "cjson") {
realOptions << "-icjson"
<< "-ocjson";
} else {
realOptions << "-icml"
<< "-ocml";
}
realOptions << "--minimize"
<< "--noh" // new in OB 3.0.1
<< "--log" << options;

Expand Down
4 changes: 2 additions & 2 deletions avogadro/qtplugins/openbabel/obprocess.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ public slots:
* optimization finishes, optimizeGeometryFinished will be emitted with the
* result of the optimization.
*
* The optimization is started with
* The optimization is started with, e.g.
* `obabel -icml -ocml --minimize <options>`
*
* The standard output is recorded and returned by optimizeGeometryFinished.
Expand All @@ -279,7 +279,7 @@ public slots:
*
* @return True if the process started successfully, false otherwise.
*/
bool optimizeGeometry(const QByteArray& cml, const QStringList& options);
bool optimizeGeometry(const QByteArray& cml, const QStringList& options, std::string format = "cml");
signals:
/**
* Emitted with the standard output of the process when it finishes.
Expand Down
Loading