-
Notifications
You must be signed in to change notification settings - Fork 121
/
ModifyDetectorDotDatFile.cpp
179 lines (156 loc) · 6.04 KB
/
ModifyDetectorDotDatFile.cpp
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
167
168
169
170
171
172
173
174
175
176
177
178
179
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source,
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
// SPDX - License - Identifier: GPL - 3.0 +
#include "MantidDataHandling/ModifyDetectorDotDatFile.h"
#include "MantidAPI/ExperimentInfo.h"
#include "MantidAPI/FileProperty.h"
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidAPI/Workspace.h"
#include "MantidGeometry/Instrument.h"
#include "MantidGeometry/Instrument/DetectorInfo.h"
#include "MantidGeometry/Instrument/RectangularDetector.h"
#include "MantidKernel/System.h"
#include <fstream>
using namespace Mantid::Kernel;
using namespace Mantid::API;
using namespace Mantid::Geometry;
namespace Mantid {
namespace DataHandling {
// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(ModifyDetectorDotDatFile)
//----------------------------------------------------------------------------------------------
/** Initialize the algorithm's properties.
*/
void ModifyDetectorDotDatFile::init() {
declareProperty(
std::make_unique<WorkspaceProperty<Workspace>>("InputWorkspace", "",
Direction::Input),
"Workspace with detectors in the positions to be put into the detector "
"dot dat file");
std::initializer_list<std::string> exts = {".dat", ".txt"};
declareProperty(
std::make_unique<FileProperty>("InputFilename", "", FileProperty::Load,
exts),
"Path to a detector dot dat file. Must be of type .dat or .txt");
declareProperty(
std::make_unique<FileProperty>("OutputFilename", "", FileProperty::Save,
exts),
"Path to the modified detector dot dat file. Must be of type .dat or "
".txt");
}
//----------------------------------------------------------------------------------------------
/** Execute the algorithm.
*/
void ModifyDetectorDotDatFile::exec() {
std::string inputFilename = getPropertyValue("InputFilename");
std::string outputFilename = getPropertyValue("OutputFilename");
Workspace_sptr ws1 = getProperty("InputWorkspace");
ExperimentInfo_sptr ws = std::dynamic_pointer_cast<ExperimentInfo>(ws1);
// Check instrument
Instrument_const_sptr inst = ws->getInstrument();
if (!inst)
throw std::runtime_error(
"No instrument in the Workspace. Cannot modify detector dot dat file");
// Open files
std::ifstream in;
in.open(inputFilename.c_str());
if (!in) {
throw Exception::FileError("Can't open input file", inputFilename);
}
std::ofstream out;
out.open(outputFilename.c_str());
if (!out) {
in.close();
throw Exception::FileError("Can't open output file", outputFilename);
}
// Read first line, modify it and put into output file
std::string str;
getline(in, str);
out << str << " and modified by MANTID algorithm ModifyDetectorDotDatFile \n";
// Read second line to check number of detectors and columns
int detectorCount, numColumns;
getline(in, str);
std::istringstream header2(str);
// what you get from the header is the Number_of_user_table_parameters
// while the number of columns must add the 5 required for the data format
header2 >> detectorCount >> numColumns;
numColumns += 5;
out << str << "\n";
// check that we have at least 1 detector and six columns
// and a reasonable number of columns. This is because, if there is not column
// specified, he will get a very large number of columns.
if (detectorCount < 1 || numColumns < 5 || numColumns > 1000) {
out.close();
in.close();
throw Exception::FileError(
"Incompatible file format found when reading line 2 in the input file",
inputFilename);
}
// Copy column title line
getline(in, str);
out << str << "\n";
// Format details
int pOffset = 3; // Precision of Offset
int pOther = 5; // Precision of Other floats
int wDet = 9; // Field width of Detector ID
int wOff = 8; // Field width of Offset
int wRad = 10; // Field width of Radius
int wCode = 6; // Field width of Code
int wAng = 12; // Field width of angles
const auto &detectorInfo = ws->detectorInfo();
// Read input file line by line, modify line as necessary and put line into
// output file
while (getline(in, str)) {
std::istringstream istr(str);
detid_t detID;
double offset;
int code;
float dump; // ignored data
if (str.empty() ||
str[0] == '#') { // comments and empty lines are allowed and just copied
out << str << "\n";
continue;
}
// First five columns in the file, the detector ID and a code for the type
// of detector CODE = 3 (psd gas tube)
istr >> detID >> offset >> dump >> code >> dump;
if (numColumns > 5)
istr >> dump; // get phi
if (code == 3) {
try {
// indexOf throws for invalided detID
V3D pos = detectorInfo.position(detectorInfo.indexOf(detID));
double l2;
double theta;
double phi;
pos.getSpherical(l2, theta, phi);
std::streampos width = istr.tellg(); // Amount of string to replace
// Some experimenting with line manipulation
std::ostringstream oss;
oss << std::fixed << std::right;
oss.precision(pOffset);
oss << std::setw(wDet) << detID << std::setw(wOff) << offset;
oss.precision(pOther);
oss << std::setw(wRad) << l2 << std::setw(wCode) << code
<< std::setw(wAng) << theta << std::setw(wAng);
if (numColumns > 5)
oss << phi; // insert phi
std::string prefix = oss.str();
std::string suffix = str.substr(width, std::string::npos);
out << prefix << suffix << "\n";
} catch (std::out_of_range &) { // Detector not found, don't modify
out << str << "\n";
}
} else {
// We do not modify any other type of line
out << str << "\n";
}
}
out.close();
in.close();
}
} // namespace DataHandling
} // namespace Mantid