Chapter 8
OUTPUT FILES
8.1 Output Files
*.out
The standard output file of ERIS.
*.pgrid
Three-dimensional voxel data storing electron or nuclear densities in a binary format. The content of this file can be visualized in three dimensions using VESTA [20] together with a crystal-structure model if necessary.
*.fba
A list of structure factors calculated by Fourier transform from electron/nuclear densities resulting from MEM analysis. This file is used by RIETAN-FP [27] for whole-pattern fitting in MPF [3–5].
*.raw
A text file storing histogram of the difference between the absolute \(F_\mathrm {o}(\bm {h}_j )\) and \(F(\bm {h}_j )\) values divided by the standard uncertainty, \(\sigma (\bm {h}_j )\), of \(|F_\mathrm {o}(\bm {h}_j )|\) to give a sample of the random variable with normalized Gaussian distribution, \(\epsilon (\mathrm {Gauss})\) [19]: \begin {equation*} \epsilon (\mathrm {Gauss}) =\frac {|F_\mathrm {o}(\bm {h}_j )| - |F(\bm {h}_j )| }{\sigma (\bm {h}_j )} \qquad (j =1\!\!-\!\!N_F) . \end {equation*} This file is useful for evaluating distribution of errors resulting from MEM analysis.
8.2 File format of *.pgrid
Volumetric data are composed of regular grids in 3D space. A volume element, “voxel,” at each grid point represents a value on the grid point. Voxels are analogous to pixels, which represent 2D image data.
8.2.1 Periodic grid vs. general grid
In general, two types of formats are used to record volumetric data in files: general and periodic grids. Figure 8.1 schematically illustrates the general concepts of the two kinds of the formats.
The general grid is a uniform one spanned inside a bounding box for molecules and a unit cell for crystals. For crystal structures, part of data in the general grid are redundant owing to the periodicity of the data. For example, a numerical value at (1, 1, 1) are equal to that at the origin, i.e, (0, 0, 0). Grids where these redundant points have been omitted are called periodic ones.

8.2.2 Pseudocode to write *.pgrid
This is a binary file storing a series of physical values in each voxel followed by some header data. Part of the C++ source code to write the header part is as follows.
char title[80]; // 80 characters of title that ends with ’\0’. int version[4] = {3, 0, 0, 0}; //The current version number is 3 0 0 0 int gType; // 0: general grid (*.ggrid); 1: periodic grid (*.pgrid). int fType; // 0: raw data; 1: paired record of index and value of voxel. int nVal; // 1 or 2; Number of data values for each voxel. int dim; // Only dimension=3 is currently supported. int nVox[3]; // Number of voxels along a, b, and c axis. // Total number of voxels to be recorded in the file. // nAsym = nVox[0]*nVox[1]*nVox[2] in the case of fType = 1. int nAsym; float cell[6]; // Unit cell parameters: a, b, c, alpha, beta, gamma // Allocate voxel data float *rho = new float[nVox[0] * nVox[1] * nVox[2] * nVal]; // Set values to the above parameters before writing them. // Write header fwrite(version, sizeof(int), 4, fptr); fwrite(title, sizeof(title), 1, fptr); fwrite(&gType, sizeof(int), 1, fptr); fwrite(&fType, sizeof(int), 1, fptr); fwrite(&nVal, sizeof(int), 1, fptr); fwrite(&dim, sizeof(int), 1, fptr); fwrite(nVox, sizeof(int), 3, fptr); fwrite(&nAsym, sizeof(int), 1, fptr); fwrite(cell, sizeof(float), 6, fptr);
For the raw data type (when fType = 0), binary data of each voxel is output in the following order.
if(fType = 0){ for(int k=0; k<nVox[2]; k++){ for(int j=0; j<nVox[1]; j++){ for(int i=0; i<nVox[0]; i++){ m = k*nVox[0]*nVox[1] + j*nVox[0] + i; for(int n=0; n<nVal; n++){ fwrite(&rho[nVal*m + n], sizeof(float), 1, fptr); } } } } }
Note that values of nVox are not the same in the case of fType = 0 (*.ggrid) and fType = 1 (*.pgrid). When saving periodic data in the former format, i.e., as the general grid format, each value of nVox is 1 voxel larger than that of the latter format. The difference is due to the redundant data points at \(x = 1\), \(y = 1\), and \(z = 1\), which are recorded in *.ggrid but not in *.pgrid. For non-periodic data, always use *.ggrid instead of *.pgrid.
When the data is periodic and space group symmetry is higher than -1, the file size can be reduced by only recording data of symmetrically independent voxels. In this case, set the parameter fType = 1 and write a list of symmetry operations before voxel data.
// Additional parameters used when fType = 1. int nPos; // Number of symmetry operations to be written. // nCen: A flag if the recorded symmetry operations need to be expanded by // inversion operation. // 0 for non-centrosymmetric space groups or when all symmetry operations // are recorded. // 1 for centrosymmetric and only half of symmetry operations are recorded. // VESTA and ERIS always record full set of symmetry operations and set // nCen=0 to allow arbitrary origin shift. int nCen; // nSub: Number of lattice points. // nSub>1 in the case of complex lattices such as I, F, A, B, C etc. // VESTA and ERIS always record full set of symmetry operations and set // nSub=1 to allow arbitrary origin shift. int nSub; // A list of lattice points in integer. // For the P-lattice, or when all symmetry operations are recorded, // subPos[1][3] = {0, 0, 0}; // subPos[2][3] = {{0, 0, 0},{nVox[0]/2, nVox[1]/2, 0}}; C-lattice // subPos[2][3] = {{0, 0, 0},{nVox[0]/2, nVox[1]/2, nVox[2]/2}}; I-lattice // etc. int subPos[NSUB][3]; // A 4x4 matrix class storing symmetry operation in column-major format. // The first 3x3 part represent rotation. // The 4th column represent translation. // An operator (i,j) in the following code is defined to return a value of // i-th raw and j-th column in double. Matrix *symOP; // A list of indices of voxel positions in asymmetric unit. int *ijk; // Set values to the above parameters before writing them. if(fType = 1){ fwrite(&nPos, sizeof(int), 1, fptr); fwrite(&nCen, sizeof(int), 1, fptr); fwrite(&nSub, sizeof(int), 1, fptr); // Write symmetry operations // A position X is transformed to X’ by X’ = symOP[i] * X. for(i=0; i<nPos; i++){ for(j=0; j<3; j++){ for(k=0; k<3; k++){ int a = (int)(symOP[i](k,j)); fwrite(&a, sizeof(int), 1, fptr); } } for(j=0; j<3; j++){ int a = (int)(symOP[i](j,3) * nVox[j]); fwrite(&a, sizeof(int), 1, fptr); } } for(i=0; i<nSub; i++){ fwrite(subPos[i], sizeof(int), 3, fptr); } // Write voxel data in asymmetric unit. // ijk is 3 indices of position of i_th voxel. for(i=0; i<nAsym; i++){ m = ijk[i*3+2]*nVox[0]*nVox[1] + ijk[i*3+1]*nVox[0] + ijk[i*3]; fwrite(&m, sizeof(int), 1, fptr); for(int n=0; n<nVal; n++){ fwrite(&rho[nVal*m + n], sizeof(float), 1, fptr); } } }

