Parsing DOSXYZnrc results
The results of a DOSXYZnrc simulation are stored in *.3ddose files containing the following blocks:
- the number of voxels in the x, y and z dimensions,
- the voxel boundary positions (cm) in the x dimension,
- the voxel boundary positions (cm) in the y dimension,
- the voxel boundary positions (cm) in the z dimension,
- the dose-per-incident-particle value array,
- and the statistical uncertainty value array
The maximum number of values contained on a line within a *.3ddose file is 5, so where a block contains more than 5 values it will be written over multiple lines. More information can be found in the DOSXYZnrc Users Manual (NRCC Report PIRS-794), packaged with BEAMnrc/DOSXYZnrc installations.
These files can be easily parsed using the following C# code as a basis. First, the file stream is opened and the number of voxels read out:
TextReader tr = new StreamReader(path);
var voxelLine = tr.ReadLine();
if (voxelLine == null) throw new NullReferenceException();
var voxels = voxelLine.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();
var data = new double[voxels[0], voxels[1], voxels[2]];
var xboundaries = new double[voxels[0] + 1];
var yboundaries = new double[voxels[1] + 1];
var zboundaries = new double[voxels[2] + 1];
Then the boundary data is processed:
var totalBoundaries = voxels[0] + voxels[1] + voxels[2] + 3;
var readBoundaries = 0;
while (boundaryNumbersRead < totalBoundaries)
{
var currLine = tr.ReadLine();
if (currLine == null) throw new NullReferenceException();
var values = currLine.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).Select(double.Parse).ToArray();
foreach (var value in values)
{
if (readBoundaries < voxels[0] + 1) xboundaries[readBoundaries] = value * 10;
else if (readBoundaries - (voxels[0] + 1) < voxels[1] + 1)
yboundaries[readBoundaries - (voxels[0] + 1)] = value * 10;
else zboundaries[readBoundaries - (voxels[0] + voxels[1] + 2)] = value * 10;
readBoundaries++;
}
}
Then the dose values are processed:
var zblocksize = voxels[0] * voxels[1];
var totalVoxels = zblocksize * voxels[2];
var readVoxels = 0;
while (readVoxels < totalVoxels)
{
var currLine = tr.ReadLine();
if (currLine == null) throw new NullReferenceException();
var values = currLine.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).Select(double.Parse).ToArray();
foreach (double v in values)
{
var z = readVoxels / zblocksize;
var y = (readVoxels / voxels[0]) % voxels[1];
var x = readVoxels % voxels[0];
dist[x, y, z] = v;
readVoxels++;
}
}
tr.Close();
The statistical uncertainty values can be parsed using the same approach used for the dose values.
The code above has not been optimised nor does it handle possibly thrown exceptions (e.g. NullReferenceException being thrown by the Split method) – it exists as an example of possible implementation.