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, even though the contents will still correspond to the xyz format.

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

Generating an Extension

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() {
}