Jpp 21.0.0-rc.1
the software that should make you happy
Loading...
Searching...
No Matches
JAlignDetector.cc
Go to the documentation of this file.
1#include <string>
2#include <iostream>
3#include <iomanip>
4#include <cmath>
5#include <vector>
6#include <set>
7
8#include "JMath/JMath.hh"
12#include "JDetector/JTripod.hh"
13
14#include "JFit/JSimplex.hh"
15#include "JLang/JException.hh"
16#include "JSupport/JMeta.hh"
17#include "JTools/JRange.hh"
18
19#include "Jeep/JContainer.hh"
20#include "Jeep/JParser.hh"
21#include "Jeep/JMessage.hh"
22
23
24namespace {
25
26 using namespace JPP;
27
28 typedef JRange<int> JRange_t;
29
30
31 // fit parameters
32
33 const char* const X_t = "x";
34 const char* const Y_t = "y";
35 const char* const Z_t = "z";
36 const char* const PHI_t = "phi";
37 const char* const TX_t = "ty";
38 const char* const TY_t = "tx";
39
40
41 /**
42 * Model for detector alignment.
43 *
44 * The model allows for a global offset of the detector position, a rotation around the z-axis and a tilt of the (x,y) plane.
45 */
46 struct JModel_t :
47 JMath<JModel_t>
48 {
49 /**
50 * Default constructor.
51 */
52 JModel_t() :
53 x (0.0),
54 y (0.0),
55 z (0.0),
56 phi(0.0),
57 tx (0.0),
58 ty (0.0)
59 {}
60
61
62 /**
63 * Constructor.
64 *
65 * \param x x
66 * \param y y
67 * \param z z
68 * \param phi phi
69 * \param tx Tx
70 * \param ty Ty
71 */
72 JModel_t(const double x,
73 const double y,
74 const double z,
75 const double phi,
76 const double tx,
77 const double ty) :
78 x (x),
79 y (y),
80 z (z),
81 phi(phi),
82 tx (tx),
83 ty (ty)
84 {}
85
86
87 /**
88 * Negate model.
89 *
90 * \return this model
91 */
92 JModel_t& negate()
93 {
94 x = -x;
95 y = -y;
96 z = -z;
97 phi = -phi;
98 tx = -tx;
99 ty = -ty;
100
101 return *this;
102 }
103
104
105 /**
106 * Add model.
107 *
108 * \param model model
109 * \return this model
110 */
111 JModel_t& add(const JModel_t& model)
112 {
113 x += model.x;
114 y += model.y;
115 z += model.z;
116 phi += model.phi;
117 tx += model.tx;
118 ty += model.ty;
119
120 return *this;
121 }
122
123
124 /**
125 * Subtract model.
126 *
127 * \param model model
128 * \return this model
129 */
130 JModel_t& sub(const JModel_t& model)
131 {
132 x -= model.x;
133 y -= model.y;
134 z -= model.z;
135 phi -= model.phi;
136 tx -= model.tx;
137 ty -= model.ty;
138
139 return *this;
140 }
141
142
143 /**
144 * Scale model.
145 *
146 * \param factor multiplication factor
147 * \return this model
148 */
149 JModel_t& mul(const double factor)
150 {
151 x *= factor;
152 y *= factor;
153 z *= factor;
154 phi *= factor;
155 tx *= factor;
156 ty *= factor;
157
158 return *this;
159 }
160
161
162 /**
163 * Scale model.
164 *
165 * \param factor division factor
166 * \return this model
167 */
168 JModel_t& div(const double factor)
169 {
170 x /= factor;
171 y /= factor;
172 z /= factor;
173 phi /= factor;
174 tx /= factor;
175 ty /= factor;
176
177 return *this;
178 }
179
180
181 double x; //!< x-offset
182 double y; //!< y-offset
183 double z; //!< z-offset
184 double phi; //!< rotation around z-axis [rad]
185 double tx; //!< tilt angle [rad]
186 double ty; //!< tilt angle [rad]
187 };
188
189
190 /**
191 * Fit function.
192 */
193 class JFit_t :
194 public JModuleRouter
195 {
196 public:
197 /**
198 * Constructor.
199 *
200 * \param detector detector (reference)
201 * \param sigma_m resolution [m]
202 * \param option option to keep strings vertical
203 * \param range range of floors used in fit
204 */
205 JFit_t(const JDetector& detector,
206 const double sigma_m,
207 const bool option,
208 const JRange_t range) :
210 sigma (sigma_m),
211 option(option),
212 range (range)
213 {
214 using namespace JPP;
215
216 center = getAverage(make_array(detector.begin(), detector.end(), &JModule::getPosition));
217
218 center.setPosition(JPosition3D(center.getX(), center.getY(), 0.0));
219 }
220
221
222 /**
223 * Get chi2.
224 *
225 * \param model model
226 * \param module module
227 * \return chi2
228 */
229 double operator()(const JModel_t& model, const JModule& module) const
230 {
231 if (this->hasModule(module.getID()) && range(module.getFloor())) {
232
233 const JPosition3D p1 = this->getModule(module.getID()).getPosition();
234 const JPosition3D p2 = this->getPosition(model, module.getPosition());
235
236 return p2.getDistanceSquared(p1) / (sigma*sigma);
237 }
238
239 return 0.0;
240 }
241
242
243 /**
244 * Get position according model.
245 *
246 * \param model model
247 * \param pos position
248 * \return position
249 */
250 JPosition3D getPosition(const JModel_t& model, const JPosition3D& pos) const
251 {
252 using namespace std;
253 using namespace JPP;
254
255 JPosition3D p1 = pos;
256
257 p1 -= center;
258
260
261 {
262 const double tx = model.tx;
263 const double tz = sqrt((1.0 + tx) * (1.0 - tx));
264
265 if (!option)
266 p1 = JPosition3D(tz * p1.getX() + tx * p1.getZ(), p1.getY(), tz * p1.getZ() - tx * p1.getX());
267 else
268 p1 = JPosition3D(tz * p1.getX(), p1.getY(), p1.getZ() - tx * p1.getX());
269 }
270 {
271 const double ty = model.ty;
272 const double tz = sqrt((1.0 + ty) * (1.0 - ty));
273
274 if (!option)
275 p1 = JPosition3D(p1.getX(), tz * p1.getY() + ty * p1.getZ(), tz * p1.getZ() - ty * p1.getY());
276 else
277 p1 = JPosition3D(p1.getX(), tz * p1.getY(), p1.getZ() - ty * p1.getY());
278 }
279
280 p1 += JPosition3D(model.x, model.y, model.z);
281 p1 += center;
282
283 return p1;
284 }
285
286 double sigma;
287 bool option;
288 JRange_t range;
289 JPosition3D center;
290 };
291}
292
293
294/**
295 * \file
296 *
297 * Auxiliary program to align two detectors.\n
298 * \author mdejong
299 */
300int main(int argc, char **argv)
301{
302 using namespace std;
303 using namespace JPP;
304
305 const set<string> PARAMETERS = { X_t, Y_t, Z_t, PHI_t, TX_t, TY_t };
306
307 string detectorFile_a;
308 string detectorFile_b;
309 bool overwriteDetector;
310 string tripodFile;
311 double sigma_m;
312 bool option;
313 JRange_t range;
314 set<string> parameters;
315 int debug;
316
317 try {
318
319 JParser<> zap("Auxiliary program to align two detectors.");
320
321 zap['a'] = make_field(detectorFile_a, "detector - subject to alignment (option -A)");
322 zap['b'] = make_field(detectorFile_b, "detector - reference for alignment");
323 zap['A'] = make_field(overwriteDetector, "overwrite detector file provided through '-a' with modified positions.");
324 zap['T'] = make_field(tripodFile, "tripods") = "";
325 zap['s'] = make_field(sigma_m) = 0.2;
326 zap['O'] = make_field(option, "keep strings vertical");
327 zap['r'] = make_field(range, "range of floors used in fit") = JRange_t();
328 zap['P'] = make_field(parameters, "fit parameters (empty = all), possible values: " << JEEPZ() << PARAMETERS) = JPARSER::initialised();
329 zap['d'] = make_field(debug) = 2;
330
331 zap(argc, argv);
332 }
333 catch(const exception &error) {
334 FATAL(error.what() << endl);
335 }
336
337
338 if (overwriteDetector) {
339 if (tripodFile == "") {
340 FATAL("No tripod file.");
341 }
342 }
343
344 for (const auto& i : parameters) {
345 if (PARAMETERS.count(i) == 0) {
346 FATAL("Invalid fit paramater " << i << ", possible values: " << JEEPZ() << PARAMETERS << endl);
347 }
348 }
349
350 JDetector detector_a;
351 JDetector detector_b;
352
353 try {
354 load(detectorFile_a, detector_a);
355 }
356 catch(const JException& error) {
357 FATAL(error);
358 }
359
360 try {
361 load(detectorFile_b, detector_b);
362 }
363 catch(const JException& error) {
364 FATAL(error);
365 }
366
367
368 const JFit_t fit(detector_b, sigma_m, option, range);
369
370 vector<JModule> data;
371
372 for (JDetector::const_iterator module = detector_a.begin(); module != detector_a.end(); ++module) {
373 if (fit.hasModule(module->getID())) {
374 data.push_back(*module);
375 }
376 }
377
378
379 JSimplex<JModel_t> simplex;
380
383
384 simplex.value = JModel_t(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
385
386
387 if (parameters.empty()) {
388 parameters = PARAMETERS;
389 }
390
391 if (parameters.count(X_t)) { simplex.step.push_back(JModel_t(0.01, 0.00, 0.00, 0.0, 0.0, 0.0)); }
392 if (parameters.count(Y_t)) { simplex.step.push_back(JModel_t(0.00, 0.01, 0.00, 0.0, 0.0, 0.0)); }
393 if (parameters.count(Z_t)) { simplex.step.push_back(JModel_t(0.00, 0.00, 0.01, 0.0, 0.0, 0.0)); }
394 if (parameters.count(PHI_t)) { simplex.step.push_back(JModel_t(0.00, 0.00, 0.00, 5.0e-4, 0.0, 0.0)); }
395 if (parameters.count(TX_t)) { simplex.step.push_back(JModel_t(0.00, 0.00, 0.00, 0.0, 1.0e-4, 0.0)); }
396 if (parameters.count(TY_t)) { simplex.step.push_back(JModel_t(0.00, 0.00, 0.00, 0.0, 0.0, 1.0e-4)); }
397
398
399 const double chi2 = simplex(fit, data.begin(), data.end());
400
401 cout << "Number of iterations " << simplex.numberOfIterations << endl;
402 cout << "chi2/NDF " << FIXED(7,3) << chi2 << '/' << (detector_a.size() - simplex.step.size()) << endl;
403
404 cout << "model:" << endl;
405
406 cout << "x " << FIXED(7,3) << simplex.value.x << endl;
407 cout << "y " << FIXED(7,3) << simplex.value.y << endl;
408 cout << "z " << FIXED(7,3) << simplex.value.z << endl;
409 cout << "phi " << FIXED(9,5) << simplex.value.phi << endl;
410 cout << "Tx " << FIXED(9,5) << simplex.value.tx << endl;
411 cout << "Ty " << FIXED(9,5) << simplex.value.ty << endl;
412
413
414 if (overwriteDetector) {
415
416 NOTICE("Store alignment data on files " << detectorFile_a << " and " << tripodFile << endl);
417
418 detector_a.comment.add(JMeta(argc,argv));
419
420 for (JDetector::iterator module = detector_a.begin(); module != detector_a.end(); ++module) {
421
422 const JPosition3D p1 = module->getPosition();
423 const JPosition3D p2 = fit.getPosition(simplex.value, p1);
424
425 module->add(p2 - p1);
426 }
427
428 try {
429 store(detectorFile_a, detector_a);
430 }
431 catch(const JException& error) {
432 FATAL(error);
433 }
434
436
437 tripods.load(tripodFile.c_str());
438
439 tripods.comment.add(JMeta(argc,argv));
440
441 for (vector<JTripod>::iterator tripod = tripods.begin(); tripod != tripods.end(); ++tripod) {
442
443 const JPosition3D p1 = tripod->getUTMPosition() - detector_a.getUTMPosition();
444 const JPosition3D p2 = fit.getPosition(simplex.value, p1);
445
446 tripod->add(p2 - p1);
447 }
448
449 tripods.store(tripodFile.c_str());
450 }
451}
int main(int argc, char **argv)
Container I/O.
Data structure for detector geometry and calibration.
TPaveText * p1
Exceptions.
Base class for data structures with artithmetic capabilities.
General purpose messaging.
#define NOTICE(A)
Definition JMessage.hh:64
#define FATAL(A)
Definition JMessage.hh:67
int debug
debug level
Definition JSirene.cc:74
ROOT I/O of application specific meta data.
Direct access to module in detector data structure.
Utility class to parse command line options.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition JParser.hh:2140
Auxiliary class to define a range between two values.
Data structure for tripod.
Detector data structure.
Definition JDetector.hh:96
int getFloor() const
Get floor number.
Definition JLocation.hh:146
Router for direct addressing of module data in detector data structure.
Data structure for a composite optical module.
Definition JModule.hh:76
Simple fit method based on Powell's algorithm, see reference: Numerical Recipes in C++,...
Definition JSimplex.hh:44
JModel_t value
Definition JSimplex.hh:240
std::vector< JModel_t > step
Definition JSimplex.hh:241
int numberOfIterations
Definition JSimplex.hh:242
Data structure for position in three dimensions.
JPosition3D & rotate(const JRotation3D &R)
Rotate.
const JPosition3D & getPosition() const
Get position.
Rotation around Z-axis.
double getDistanceSquared(const JVector3D &pos) const
Get squared of distance to point.
Definition JVector3D.hh:258
General exception.
Definition JException.hh:25
int getID() const
Get identifier.
Definition JObjectID.hh:63
Utility class to parse command line options.
Definition JParser.hh:1697
Range of values.
Definition JRange.hh:42
const JUTMPosition & getUTMPosition() const
Get UTM position.
JPosition3D getPosition(const Vec &pos)
Get position.
const JModule & getModule(const JType< JDetector_t > type, const int id, const JLocation &location=JLocation())
Get module according given detector type.
void load(const std::string &file_name, JDetector &detector)
Load detector from input file.
void store(const std::string &file_name, const JDetector &detector)
Store detector to output file.
void model(JModel_t &value)
Auxiliary function to constrain model during fit.
Definition JGandalf.hh:57
array_type< JValue_t > make_array(const JValue_t(&array)[N])
Method to create array of values.
Definition JVectorize.hh:69
std::iterator_traits< T >::value_type getAverage(T __begin, T __end)
Get average.
Definition JMath.hh:494
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
Auxiliary data structure for floating point format specification.
Definition JManip.hh:448
Type definition of range.
Definition JHead.hh:43
Detector file.
Definition JHead.hh:227
JComment & add(const std::string &comment)
Add comment.
Definition JComment.hh:100
Auxiliary wrapper for I/O of container with optional comment (see JComment).
Definition JContainer.hh:42
Auxiliary data structure for streaming of STL containers.
void store(const char *file_name) const
Store to output file.
void load(const char *file_name)
Load from input file.
Auxiliary base class for aritmetic operations of derived class types.
Definition JMath.hh:347
Empty structure for specification of parser element that is initialised (i.e. does not require input)...
Definition JParser.hh:67
Auxiliary class for ROOT I/O of application specific meta data.
Definition JMeta.hh:72