Exporting data

In this tutorial, we will create an exporter for the following XYZ format: The 1st line: the number of atoms in the file. The 2nd line: arbitraty header line. Next lines contain information on atoms in the following format (coordinates are in angstroms): element_symbol x-coordinate y-coordinate z-coordinate.

Example of the format:

10
SAMSON Export
C -6.644 9.967 5.557
C -7.934 9.831 4.773
C -7.934 10.816 3.617
C -8.098 8.407 4.266
N -7.404 9.603 7.84
C -6.46 9.161 6.834
C -5.09 9.488 7.383
O -5.008 10.375 8.245
H -8.382 9.481 7.521
H -7.182 10.599 8.021

Note: SAMSON already has an XYZ Exporter which is installed by default, that's why we are actually going to read files with a exyz extension (e for element), even though the contents will still correspond to the xyz format.

The source code for an Element created in this tutorial can be found at https://github.com/1A-OneAngstrom/SAMSON-Developer-Tutorials.

Generating an Element

We will start by creating a new SAMSON Element called EXYZ thanks to the SAMSON Element generator (please, refer to the SAMSON Element generator tutorial for a reminder on how to use it):

The SAMSON Element generator generates an exporter class (derived from the SBIFileExporter class) and a GUI class that implements the user interface of the exporter and is derived from the SBGFileExporter class.

Exporting into a file

In SAMSON, an exporter is created by programming three functions in the exporter class:

Let's open the SEEXYZExporter.cpp file and implement these functions.

Modify the getExtension function to return the extension of the exporter (exyz) as follows:

std::string SEEXYZExporter::getExtension() const {
return std::string("exyz");
}

Modify the getFilter function to return the filter of the exporter as follows (it should be in the Qt format):

std::string SEEXYZExporter::getFilter() const {
return std::string("EXYZ format (*.exyz)");
}

We now have to code the exportToFile function to export atoms into a exyz file. To achieve this, we are going to use fstream to create and write into a file, the SAMSON class to get atoms from the active document, and several structural classes. For that, include the following headers in the file:

#include <fstream>
#include "SAMSON.hpp"
#include "SBStructuralModel.hpp"
#include "SBAtom.hpp"

Let's now code inside the exportToFile function:

bool SEEXYZExporter::exportToFile(const SBNodeIndexer& nodeIndexer, const std::string& fileName, const SBList<std::string>* parameters)

First, we find all atoms in the nodes that were passed to the exportToFile function:

// retrieve all atoms
SBNodeIndexer atomIndexer;
SB_FOR(SBNode* node, nodeIndexer) node->getNodes(atomIndexer, SBNode::IsType(SBNode::Atom));

Recall that SBNode::IsType(SBNode::Atom) is a predicate, passed to the getNodes function, that returns true for nodes that are atoms.

If the user saves data via File > Save or File > Save as... it will export all atoms from the active document, if the user saves data via File > Save selection as... it will export all atoms from the selection in the active document.

Then, we create the file and write its header:

// create file
ofstream file;
file.open(fileName.c_str());
// write the header
file << atomIndexer.size() << std::endl; // number of atoms
file << "SAMSON Export" << std::endl;

In this tutorial, for simplicity we do not check for errors during the creation and writing of the file.

And we then write the description of each atom to the file:

// write atoms
for (unsigned int i = 0; i < atomIndexer.size(); i++) {
SBAtom* currentAtom = static_cast<SBAtom*>(atomIndexer[i]);
SBPosition3 const& currentAtomPosition = currentAtom->getPosition();
file << SAMSON::getElementSymbol(currentAtom->getElementType())
<< " " << SBQuantity::angstrom(currentAtomPosition.v[0]).getValue()
<< " " << SBQuantity::angstrom(currentAtomPosition.v[1]).getValue()
<< " " << SBQuantity::angstrom(currentAtomPosition.v[2]).getValue() << "\n";
}

Finally, we close the file and we signal that everything went fine (at least we believe so, since we didn’t test for errors in this tutorial):

// close the file
file.close();
return true;

That is it. You can now export into exyz format.

If you want for the Exporter to get some parameters/options from the user, please check out to the Importer tutorial: Getting parameters, if not then you can simply disable the options window by replacing the constructor and destructor of SEEXYZExporter as follows:

SEEXYZExporter::SEEXYZExporter() {
// remove the options window
propertyDialog = 0;
}
SEEXYZExporter::~SEEXYZExporter() {
}