From e1dbd34ac8811363d07a5a3409d6a167abfd63ec Mon Sep 17 00:00:00 2001 From: Geoff Hutchison Date: Wed, 2 Jun 2021 11:29:47 -0400 Subject: [PATCH] Transparent support for ASE "extended XYZ" files These XYZ files include unit cell "Lattice" in the title line: e.g. Lattice="H11 H21 H31 H12 H22 H32 H13 H23 H33" https://atomsk.univ-lille.fr/doc/en/format_xyz.html https://gitlab.com/ase/ase/-/merge_requests/62 Significantly improve support for ASE and other solid-state codes Signed-off-by: Geoff Hutchison --- avogadro/io/xyzformat.cpp | 83 +++++++++++++++++++++++++++------------ avogadro/io/xyzformat.h | 13 +----- 2 files changed, 59 insertions(+), 37 deletions(-) diff --git a/avogadro/io/xyzformat.cpp b/avogadro/io/xyzformat.cpp index 610242a12f..3bfa03d5c5 100644 --- a/avogadro/io/xyzformat.cpp +++ b/avogadro/io/xyzformat.cpp @@ -1,23 +1,13 @@ /****************************************************************************** - 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 "xyzformat.h" #include #include +#include #include #include @@ -31,10 +21,10 @@ using json = nlohmann::json; -using std::string; using std::endl; using std::getline; using std::string; +using std::string; using std::vector; namespace Avogadro { @@ -52,13 +42,9 @@ using Core::trimmed; using std::isalpha; #endif -XyzFormat::XyzFormat() -{ -} +XyzFormat::XyzFormat() {} -XyzFormat::~XyzFormat() -{ -} +XyzFormat::~XyzFormat() {} bool XyzFormat::read(std::istream& inStream, Core::Molecule& mol) { @@ -80,6 +66,31 @@ bool XyzFormat::read(std::istream& inStream, Core::Molecule& mol) if (!buffer.empty()) mol.setData("name", trimmed(buffer)); + // check for Lattice= in an extended XYZ from ASE and company + // e.g. Lattice="H11 H21 H31 H12 H22 H32 H13 H23 H33" + // https://atomsk.univ-lille.fr/doc/en/format_xyz.html + // https://gitlab.com/ase/ase/-/merge_requests/62 + std::size_t start = buffer.find("Lattice=\""); + if (start != std::string::npos) { + // step through bit by bit until we hit the next quote character + start = start + 9; + std::size_t end = buffer.find('\"', start); + std::string lattice = buffer.substr(start, (end - start)); + + vector tokens(split(lattice, ' ')); + if (tokens.size() == 9) { + Vector3 v1(lexicalCast(tokens[0]), lexicalCast(tokens[1]), + lexicalCast(tokens[2])); + Vector3 v2(lexicalCast(tokens[3]), lexicalCast(tokens[4]), + lexicalCast(tokens[5])); + Vector3 v3(lexicalCast(tokens[6]), lexicalCast(tokens[7]), + lexicalCast(tokens[8])); + + Core::UnitCell* cell = new Core::UnitCell(v1, v2, v3); + mol.setUnitCell(cell); + } + } + // Parse atoms for (size_t i = 0; i < numAtoms; ++i) { getline(inStream, buffer); @@ -162,10 +173,31 @@ bool XyzFormat::write(std::ostream& outStream, const Core::Molecule& mol) size_t numAtoms = mol.atomCount(); outStream << numAtoms << std::endl; - if (mol.data("name").toString().length()) - outStream << mol.data("name").toString() << endl; - else - outStream << "XYZ file generated by Avogadro.\n"; + + if (mol.unitCell()) { + // default to including Lattice for extended XYZ if present + // https://atomsk.univ-lille.fr/doc/en/format_xyz.html + // https://gitlab.com/ase/ase/-/merge_requests/62 + outStream << "Lattice=\""; + outStream << mol.unitCell()->aVector().x() << ' '; + outStream << mol.unitCell()->aVector().y() << ' '; + outStream << mol.unitCell()->aVector().z() << ' '; + + outStream << mol.unitCell()->bVector().x() << ' '; + outStream << mol.unitCell()->bVector().y() << ' '; + outStream << mol.unitCell()->bVector().z() << ' '; + + outStream << mol.unitCell()->cVector().x() << ' '; + outStream << mol.unitCell()->cVector().y() << ' '; + outStream << mol.unitCell()->cVector().z(); + + outStream << "\" Properties=species:S:1:pos:R:3" << endl; + } else { + if (mol.data("name").toString().length()) + outStream << mol.data("name").toString() << endl; + else + outStream << "XYZ file generated by Avogadro.\n"; + } for (size_t i = 0; i < numAtoms; ++i) { Atom atom = mol.atom(i); @@ -190,6 +222,7 @@ std::vector XyzFormat::fileExtensions() const { std::vector ext; ext.push_back("xyz"); + ext.push_back("extxyz"); return ext; } @@ -200,5 +233,5 @@ std::vector XyzFormat::mimeTypes() const return mime; } -} // end Io namespace -} // end Avogadro namespace +} // namespace Io +} // namespace Avogadro diff --git a/avogadro/io/xyzformat.h b/avogadro/io/xyzformat.h index c2be0d4e55..a8ada388d6 100644 --- a/avogadro/io/xyzformat.h +++ b/avogadro/io/xyzformat.h @@ -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_IO_XYZFORMAT_H