Exporting files#
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 SAMSON-Developer-Tutorials.
Generating an Extension#
We will start by creating a new SAMSON Extension called EXYZ thanks to the SAMSON Extension Generator (please, refer to the SAMSON Extension Generator tutorial for a reminder on how to use it):
- launch SAMSON and run the SAMSON Extension Generator;
- specify the path to a folder where you want to develop your SAMSON Extensions;
- name the SAMSON Extension as EXYZ and add some description;
- add an Exporter class (called
SEEXYZExporter
); - generate the SAMSON Extension.
The SAMSON Extension 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:
getExtension
- specifies the extension of a file;getFilter
- specifies a filter in Qt format;exportToFile
- a function invoked by SAMSON to export into a file with a suitable extension.
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:
Modify the getFilter
function to return the filter of the exporter as follows (it should be in the Qt format):
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:
Let's now code inside the exportToFile
function:
bool SEEXYZExporter::exportToFile(
const SBNodeIndexer& nodeIndexer,
const std::string& fileName,
const std::unordered_map<std::string, SBValue>* 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 Home > File > Save or Home > File > Save as... it will export all atoms from the active document, if the user saves data via Home > 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):
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: