Skip to content

Commit

Permalink
Merge pull request #1452 from ghutchis/add-msgpack
Browse files Browse the repository at this point in the history
Add new MessagePack version of CJSON
  • Loading branch information
ghutchis authored Nov 13, 2023
2 parents 7462dd9 + 606254f commit 0087271
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 20 deletions.
2 changes: 2 additions & 0 deletions avogadro/io/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ add_library(IO)
avogadro_headers(IO
cjsonformat.h
cmlformat.h
cmsgpackformat.h
dcdformat.h
fileformat.h
fileformatmanager.h
Expand All @@ -19,6 +20,7 @@ avogadro_headers(IO
target_sources(IO PRIVATE
cjsonformat.cpp
cmlformat.cpp
cmsgpackformat.cpp
dcdformat.cpp
fileformat.cpp
fileformatmanager.cpp
Expand Down
32 changes: 27 additions & 5 deletions avogadro/io/cjsonformat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,18 @@ bool isBooleanArray(json& j)

bool CjsonFormat::read(std::istream& file, Molecule& molecule)
{
json jsonRoot = json::parse(file, nullptr, false);
return deserialize(file, molecule, true);
}

bool CjsonFormat::deserialize(std::istream& file, Molecule& molecule,
bool isJson)
{
json jsonRoot;
if (isJson)
jsonRoot = json::parse(file, nullptr, false);
else // msgpack
jsonRoot = json::from_msgpack(file);

if (jsonRoot.is_discarded()) {
appendError("Error reading CJSON file.");
return false;
Expand Down Expand Up @@ -634,6 +645,12 @@ bool CjsonFormat::read(std::istream& file, Molecule& molecule)
}

bool CjsonFormat::write(std::ostream& file, const Molecule& molecule)
{
return serialize(file, molecule, true);
}

bool CjsonFormat::serialize(std::ostream& file, const Molecule& molecule,
bool isJson)
{
json opts;
if (!options().empty())
Expand Down Expand Up @@ -1015,7 +1032,8 @@ bool CjsonFormat::write(std::ostream& file, const Molecule& molecule)
modes.push_back(static_cast<unsigned int>(i) + 1);
freqs.push_back(molecule.vibrationFrequencies()[i]);
inten.push_back(molecule.vibrationIRIntensities()[i]);
raman.push_back(molecule.vibrationRamanIntensities()[i]);
if (molecule.vibrationRamanIntensities().size() > i)
raman.push_back(molecule.vibrationRamanIntensities()[i]);
Core::Array<Vector3> atomDisplacements = molecule.vibrationLx(i);
json eigenVector;
for (auto pos : atomDisplacements) {
Expand All @@ -1028,7 +1046,8 @@ bool CjsonFormat::write(std::ostream& file, const Molecule& molecule)
root["vibrations"]["modes"] = modes;
root["vibrations"]["frequencies"] = freqs;
root["vibrations"]["intensities"] = inten;
root["vibrations"]["ramanIntensities"] = raman;
if (molecule.vibrationRamanIntensities().size() > 0)
root["vibrations"]["ramanIntensities"] = raman;
root["vibrations"]["eigenVectors"] = eigenVectors;
}

Expand Down Expand Up @@ -1059,8 +1078,11 @@ bool CjsonFormat::write(std::ostream& file, const Molecule& molecule)
root["layer"]["settings"][settings.first] = setting;
}

// Write out the file, use a two space indent to "pretty print".
file << std::setw(2) << root;
if (isJson)
file << std::setw(2) << root;
else { // write msgpack
json::to_msgpack(root, file);
}

return true;
}
Expand Down
10 changes: 7 additions & 3 deletions avogadro/io/cjsonformat.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,21 @@ class AVOGADROIO_EXPORT CjsonFormat : public FileFormat

std::string specificationUrl() const override
{
return "http://wiki.openchemistry.org/Chemical_JSON";
return "https://github.com/openchemistry/chemicaljson";
}

std::vector<std::string> fileExtensions() const override;
std::vector<std::string> mimeTypes() const override;

bool read(std::istream& in, Core::Molecule& molecule) override;
bool write(std::ostream& out, const Core::Molecule& molecule) override;

// internal - to allow JSON or MsgPack to be written
bool deserialize(std::istream& in, Core::Molecule& molecule, bool json);
bool serialize(std::ostream& out, const Core::Molecule& molecule, bool json);
};

} // end Io namespace
} // end Avogadro namespace
} // namespace Io
} // namespace Avogadro

#endif // AVOGADRO_IO_CJSONFORMAT_H
45 changes: 45 additions & 0 deletions avogadro/io/cmsgpackformat.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/******************************************************************************
This source file is part of the Avogadro project.
This source code is released under the 3-Clause BSD License, (see "LICENSE").
******************************************************************************/

#include "cmsgpackformat.h"

#include <iostream>

using namespace std;

namespace Avogadro::Io {

CMsgPackFormat::CMsgPackFormat() : CjsonFormat()
{
m_json = false;
}

CMsgPackFormat::~CMsgPackFormat() = default;

vector<std::string> CMsgPackFormat::fileExtensions() const
{
vector<std::string> ext;
ext.emplace_back("cmpk");
return ext;
}

vector<std::string> CMsgPackFormat::mimeTypes() const
{
vector<std::string> mime;
mime.emplace_back("chemical/x-cmpack");
return mime;
}

bool CMsgPackFormat::read(std::istream& in, Core::Molecule& molecule)
{
return CjsonFormat::deserialize(in, molecule, false);
}

bool CMsgPackFormat::write(std::ostream& out, const Core::Molecule& molecule)
{
return CjsonFormat::serialize(out, molecule, false);
}

} // namespace Avogadro::Io
62 changes: 62 additions & 0 deletions avogadro/io/cmsgpackformat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/******************************************************************************
This source file is part of the Avogadro project.
This source code is released under the 3-Clause BSD License, (see "LICENSE").
******************************************************************************/

#ifndef AVOGADRO_IO_CMSGPACKFORMAT_H
#define AVOGADRO_IO_CMSGPACKFORMAT_H

#include "cjsonformat.h"
#include "fileformat.h"

namespace Avogadro {
namespace Core {
class GaussianSet;
}
namespace Io {

/**
* @class CMsgPackFormat cmsgpackformat.h <avogadro/io/cmsgpackformat.h>
* @brief Implementation of the Chemical MessagePack format.
*/

class AVOGADROIO_EXPORT CMsgPackFormat : public CjsonFormat
{
public:
CMsgPackFormat();
~CMsgPackFormat() override;

Operations supportedOperations() const override
{
return ReadWrite | File | Stream | String;
}

FileFormat* newInstance() const override { return new CMsgPackFormat; }
std::string identifier() const override { return "Avogadro: CMsgPack"; }
std::string name() const override { return "Chemical MessagePack"; }
std::string description() const override
{
return "CMsgPack format is a lightweight intermediate format used to "
"exchange "
"information between Avogadro and other data parsing applications";
}

std::string specificationUrl() const override
{
return "https://github.com/openchemistry/chemicaljson";
}

std::vector<std::string> fileExtensions() const override;
std::vector<std::string> mimeTypes() const override;

bool read(std::istream& in, Core::Molecule& molecule) override;
bool write(std::ostream& out, const Core::Molecule& molecule) override;

// write MessagePack
bool m_json = false;
};

} // namespace Io
} // namespace Avogadro

#endif // AVOGADRO_IO_CMSGPACKFORMAT_H
25 changes: 13 additions & 12 deletions avogadro/io/fileformatmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "cjsonformat.h"
#include "cmlformat.h"
#include "cmsgpackformat.h"
#include "dcdformat.h"
#include "gromacsformat.h"
#include "lammpsformat.h"
Expand Down Expand Up @@ -134,7 +135,7 @@ bool FileFormatManager::addFormat(FileFormat* format)
appendError("Format " + format->identifier() + " already loaded.");
return false;
}
for (auto & m_format : m_formats) {
for (auto& m_format : m_formats) {
if (m_format == format) {
appendError("The format object was already loaded.");
return false;
Expand All @@ -146,11 +147,11 @@ bool FileFormatManager::addFormat(FileFormat* format)
m_formats.push_back(format);
m_identifiers[format->identifier()].push_back(index);
std::vector<std::string> mimes = format->mimeTypes();
for (auto & mime : mimes) {
for (auto& mime : mimes) {
m_mimeTypes[mime].push_back(index);
}
std::vector<std::string> extensions = format->fileExtensions();
for (auto & extension : extensions) {
for (auto& extension : extensions) {
m_fileExtensions[extension].push_back(index);
}

Expand All @@ -160,7 +161,7 @@ bool FileFormatManager::addFormat(FileFormat* format)
namespace {
// Lookup each key from "keys" in "map", and remove "val" from the Map's
// data value (which is a vector of ValueType)
template<typename Map, typename VectorOfKeys, typename ValueType>
template <typename Map, typename VectorOfKeys, typename ValueType>
void removeFromMap(Map& map, const VectorOfKeys& keys, const ValueType& val)
{
for (auto key = keys.begin(), keyEnd = keys.end(); key != keyEnd; ++key) {
Expand All @@ -171,13 +172,12 @@ void removeFromMap(Map& map, const VectorOfKeys& keys, const ValueType& val)
if (vec.size() <= 1) {
map.erase(*key);
} else {
auto newEnd =
std::remove(vec.begin(), vec.end(), val);
auto newEnd = std::remove(vec.begin(), vec.end(), val);
vec.resize(newEnd - vec.begin());
}
}
}
}
} // namespace

bool FileFormatManager::removeFormat(const std::string& identifier)
{
Expand Down Expand Up @@ -284,6 +284,7 @@ FileFormatManager::FileFormatManager()
{
addFormat(new CmlFormat);
addFormat(new CjsonFormat);
addFormat(new CMsgPackFormat);
addFormat(new DcdFormat);
addFormat(new GromacsFormat);
addFormat(new LammpsTrajectoryFormat);
Expand All @@ -303,7 +304,7 @@ FileFormatManager::FileFormatManager()
FileFormatManager::~FileFormatManager()
{
// Delete the file formats that were loaded.
for (auto & m_format : m_formats) {
for (auto& m_format : m_formats) {
delete m_format;
}
m_formats.clear();
Expand All @@ -314,9 +315,9 @@ std::vector<std::string> FileFormatManager::filteredKeysFromFormatMap(
const FileFormatManager::FormatIdMap& fmap) const
{
std::vector<std::string> result;
for (const auto & it : fmap) {
for (auto formatIt = it.second.begin();
formatIt != it.second.end(); ++formatIt) {
for (const auto& it : fmap) {
for (auto formatIt = it.second.begin(); formatIt != it.second.end();
++formatIt) {
if (filter == FileFormat::None ||
(m_formats[*formatIt]->supportedOperations() & filter) == filter) {
result.push_back(it.first);
Expand Down Expand Up @@ -383,4 +384,4 @@ void FileFormatManager::appendError(const std::string& errorMessage)
m_error += errorMessage + "\n";
}

} // end Avogadro namespace
} // namespace Avogadro::Io

0 comments on commit 0087271

Please sign in to comment.