1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
// ************************************************************************************************
//
// BornAgain: simulate and fit reflection and scattering
//
//! @file Device/IO/ReadWriteNicos.cpp
//! @brief Implements function Util::RW::readNicos.
//!
//! @homepage http://www.bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2021
//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
// ************************************************************************************************
#include "Device/IO/ReadWriteNicos.h"
#include "Base/Axis/Frame.h"
#include "Base/Axis/MakeScale.h"
#include "Base/Util/StringUtil.h"
#include "Device/Data/Datafield.h"
#include <memory>
namespace {
std::string lineRelatedError(const std::string& errorText, int lineNumber)
{
return "Line " + std::to_string(lineNumber) + ": " + errorText;
}
unsigned int readAssignedPositiveIntValue(const std::string& line, int lineNumber)
{
const auto parts = Base::String::split(line, "=");
if (parts.size() != 2)
throw std::runtime_error(lineRelatedError("Missing assigned value", lineNumber));
int value = 0;
if (!Base::String::to_int(parts[1], &value))
throw std::runtime_error(
lineRelatedError("Cannot parse assigned value '" + parts[1] + "'", lineNumber));
if (value <= 0)
throw std::runtime_error(
lineRelatedError("Value of '" + parts[1] + "' is nonpositive", lineNumber));
return value;
}
} // namespace
Datafield Util::RW::readNicos(std::istream& input_stream)
{
std::string line;
int lineNumber = 0;
unsigned int width = 0;
unsigned int height = 0;
// -- read dimensions
bool inFileSection = false;
bool fileSectionFound = false;
bool typeFound = false;
while (std::getline(input_stream, line)) {
lineNumber++;
line = Base::String::trimFront(line, " ");
if (!inFileSection) {
if (Base::String::startsWith(line, "%File")) {
inFileSection = true;
fileSectionFound = true;
continue;
}
continue;
}
if (Base::String::startsWith(line, "%"))
break; // next section
if (Base::String::startsWith(line, "Type=")) {
const auto parts = Base::String::split(line, "=");
if (parts[1] != "SANSDRaw")
throw std::runtime_error(
lineRelatedError("Unsupported file type '" + parts[1] + "'", lineNumber));
typeFound = true;
}
if (Base::String::startsWith(line, "DataSizeX"))
width = readAssignedPositiveIntValue(line, lineNumber);
else if (Base::String::startsWith(line, "DataSizeY"))
height = readAssignedPositiveIntValue(line, lineNumber);
if (width != 0 && height != 0)
break;
}
if (!fileSectionFound)
throw std::runtime_error("Could not find 'File' section");
if (!typeFound)
throw std::runtime_error("File type not found");
if (width == 0)
throw std::runtime_error("Could not find 'DataSizeX' value");
if (height == 0)
throw std::runtime_error("Could not find 'DataSizeY' value");
std::vector<const Scale*> axes{newEquiDivision("u (bin)", width, 0.0, width),
newEquiDivision("v (bin)", height, 0.0, height)};
auto result = std::make_unique<Datafield>(axes);
// -- read data
bool inCountSection = false;
bool countSectionFound = false;
unsigned int dataRow = 0;
while (std::getline(input_stream, line)) {
lineNumber++;
line = Base::String::trimFront(line, " ");
if (!inCountSection) {
if (Base::String::startsWith(line, "%Counts")) {
inCountSection = true;
countSectionFound = true;
continue;
}
continue;
}
if (Base::String::startsWith(line, "%"))
break; // next section
// line is a data line
line = Base::String::trim(line, " ");
if (line.empty())
continue;
const auto valuesAsString = Base::String::split(line, ",");
if (valuesAsString.size() != width)
throw std::runtime_error(
lineRelatedError("Number of found values (" + std::to_string(valuesAsString.size())
+ ") does not match DataSizeX (" + std::to_string(width) + ")",
lineNumber));
for (unsigned col = 0; col < width; ++col) {
int value = 0;
if (!Base::String::to_int(valuesAsString[col], &value))
throw std::runtime_error(lineRelatedError(
"Value '" + valuesAsString[col] + "' could not be converted to integer",
lineNumber));
// y-axis "0" is at bottom => invert y
// to show first line at top of image
(*result)[(height - 1 - dataRow) * width + col] = value;
}
dataRow++;
if (dataRow == height)
break;
}
if (!countSectionFound)
throw std::runtime_error("Could not find 'Counts' section");
if (dataRow != height)
throw std::runtime_error("Number of found data rows (" + std::to_string(dataRow)
+ ") does not match DataSizeY (" + std::to_string(height) + ")");
return *result;
}
|