Jpp 19.3.0
the software that should make you happy
Loading...
Searching...
No Matches
JDetectorToolkit.hh
Go to the documentation of this file.
1#ifndef __JDETECTOR__JDETECTORTOOLKIT__
2#define __JDETECTOR__JDETECTORTOOLKIT__
3
4#include <limits>
5#include <istream>
6#include <ostream>
7#include <iostream>
8#include <fstream>
9#include <cmath>
10#include <vector>
11#include <set>
12#include <algorithm>
13#include <cstdlib>
14
26#include "JMath/JConstants.hh"
27#include "JMath/JMathToolkit.hh"
28#include "JTools/JRange.hh"
29#include "JIO/JFileStreamIO.hh"
30#include "Jeep/JeepToolkit.hh"
31#include "JLang/JException.hh"
32#include "JLang/gzstream.h"
33#include "JLang/JManip.hh"
34#include "JLang/Jpp.hh"
35
36
37/**
38 * \author mdejong
39 */
40
41namespace JDETECTOR {}
42namespace JPP { using namespace JDETECTOR; }
43
44/**
45 * Auxiliary classes and methods for detector calibration and simulation.
46 */
47namespace JDETECTOR {
48
54
55
56 /**
57 * File name extensions.
58 */
59 static const char* const GENDET_DETECTOR_FILE_FORMAT = "det"; //!< file format used by gendet
60 static const char* const BINARY_DETECTOR_FILE_FORMAT[] = { "dat", "datx" }; //!< JIO binary file format
61 static const char* const KM3NET_DETECTOR_FILE_FORMAT = "detx"; //!< %KM3NeT standard ASCII format
62 static const char* const ZIPPED_DETECTOR_FILE_FORMAT = "gz"; //!< zipped %KM3NeT standard ASCII format
63 static const char* const GDML_DETECTOR_FILE_FORMAT = "gdml"; //!< KM3Sim input format
64
65 static const char* const GDML_SCHEMA = getenv("GDML_SCHEMA_DIR"); //!< directory necessary for correct GDML header output
66 static const char* const CAN_MARGIN_M = getenv("CAN_MARGIN_M"); //!< extension of the detector size to comply with the can definition
67 static const char* const G4GDML_DEFAULT_SCHEMALOCATION = "http://service-spi.web.cern.ch/service-spi/app/releases/GDML/schema/gdml.xsd";
68
69
70 /**
71 * Get maximal distance between modules in detector.
72 * The option can be used to include base modules, if any.
73 *
74 * \param detector detector
75 * \param option option
76 * \return maximal distance [m]
77 */
78 inline double getMaximalDistance(const JDetector& detector, const bool option = false)
79 {
80 using namespace JPP;
81
82 double dmax = 0.0;
83
84 for (JDetector::const_iterator i1 = detector.begin(); i1 != detector.end(); ++i1) {
85 for (JDetector::const_iterator i2 = detector.begin(); i2 != i1; ++i2) {
86
87 if (option || (i1->getFloor() != 0 && i2->getFloor() != 0)) {
88
89 const double ds = getDistance(i1->getPosition(), i2->getPosition());
90
91 if (ds > dmax) {
92 dmax = ds;
93 }
94 }
95 }
96 }
97
98 return dmax;
99 }
100
101
102 /**
103 * Get minimal distance between modules in detector.
104 *
105 * \param detector detector
106 * \return minimal distance [m]
107 */
109 {
110 using namespace std;
111 using namespace JPP;
112
113 double dmin = numeric_limits<double>::max();
114
115 for (JDetector::const_iterator i1 = detector.begin(); i1 != detector.end(); ++i1) {
116 for (JDetector::const_iterator i2 = detector.begin(); i2 != i1; ++i2) {
117
118 const double ds = getDistance(i1->getPosition(), i2->getPosition());
119
120 if (ds < dmin) {
121 dmin = ds;
122 }
123 }
124 }
125
126 return dmin;
127 }
128
129
130 /**
131 * Get maximal time between optical modules in detector following causality.
132 *
133 * \param detector detector
134 * \return maximal time [ns]
135 */
136 inline double getMaximalTime(const JDetector& detector)
137 {
138 using namespace JPP;
139
140 return getMaximalDistance(detector) * getIndexOfRefraction() * getInverseSpeedOfLight();
141 }
142
143
144 /**
145 * Get maximal time between optical modules in detector following causality.
146 * The road width corresponds to the maximal distance traveled by the light.
147 *
148 * \param detector detector
149 * \param roadWidth_m road width [m]
150 * \return maximal time [ns]
151 */
152 inline double getMaximalTime(const JDetector& detector, const double roadWidth_m)
153 {
154 using namespace JPP;
155
156 const double Dmax_m = getMaximalDistance(detector);
157
158 return (sqrt((Dmax_m + roadWidth_m*getSinThetaC()) *
159 (Dmax_m - roadWidth_m*getSinThetaC())) +
160 roadWidth_m * getSinThetaC() * getTanThetaC()) * getInverseSpeedOfLight();
161 }
162
163
164 /**
165 * Get de-calibrated time range.
166 *
167 * The de-calibrated time range is corrected for minimal and maximal time offset of PMTs in given module.
168 *
169 * \param timeRange time range [ns]
170 * \param module module
171 * \return time range [ns]
172 */
173 inline JTimeRange getTimeRange(const JTimeRange& timeRange, const JModule& module)
174 {
175 if (!module.empty()) {
176
178
179 for (JModule::const_iterator pmt = module.begin(); pmt != module.end(); ++pmt) {
180
181 const JCalibration& calibration = pmt->getCalibration();
182
183 time_range.include(putTime(timeRange.getLowerLimit(), calibration));
184 time_range.include(putTime(timeRange.getUpperLimit(), calibration));
185 }
186
187 return time_range;
188
189 } else {
190
191 return timeRange;
192 }
193 }
194
195
196 /**
197 * Get number of PMTs.
198 *
199 * \param module module
200 * \return number of PMTs
201 */
202 inline int getNumberOfPMTs(const JModule& module)
203 {
204 return module.size();
205 }
206
207
208 /**
209 * Get number of PMTs.
210 *
211 * \param detector detector
212 * \return number of PMTs
213 */
215 {
216 int number_of_pmts = 0;
217
218 for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
219 number_of_pmts += getNumberOfPMTs(*module);
220 }
221
222 return number_of_pmts;
223 }
224
225
226 /**
227 * Get list of strings identifiers.
228 *
229 * \param detector detector
230 * \return list of string identifiers
231 */
233 {
234 std::set<int> buffer;
235
236 for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
237 buffer.insert(module->getString());
238 }
239
240 return buffer;
241 }
242
243
244 /**
245 * Get list of modules identifiers.
246 *
247 * \param detector detector
248 * \param option option to include base modules
249 * \return list of module identifiers
250 */
251 inline std::set<int> getModuleIDs(const JDetector& detector, const bool option = false)
252 {
253 std::set<int> buffer;
254
255 for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
256 if (option || !module->empty()) {
257 buffer.insert(module->getID());
258 }
259 }
260
261 return buffer;
262 }
263
264
265 /**
266 * Get number of floors.
267 *
268 * \param detector detector
269 * \return number of floors
270 */
272 {
273 std::set<int> buffer;
274
275 for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
276 buffer.insert(module->getFloor());
277 }
278
279 return buffer.size();
280 }
281
282
283 /**
284 * Type definition for range of floors.
285 */
287
288
289 /**
290 * Get range of floors.
291 *
292 * \param detector detector
293 * \return range of floors
294 */
296 {
298
299 for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
300 buffer.include(module->getFloor());
301 }
302
303 return buffer;
304 }
305
306
307 /**
308 * Get number of modules.
309 *
310 * \param detector detector
311 * \param option option to include base modules
312 * \return number of modules
313 */
314 inline int getNumberOfModules(const JDetector& detector, const bool option = false)
315 {
316 std::set<int> buffer;
317
318 for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
319 if (option || !module->empty()) {
320 buffer.insert(module->getID());
321 }
322 }
323
324 return buffer.size();
325 }
326
327
328 /**
329 * Get rotation over X axis in Geant4 coordinate system
330 *
331 * \param dir direction
332 * \return X-rotation [deg]
333 */
334 inline double GetXrotationG4(const JVersor3D& dir)
335 {
336 using namespace JPP;
337
338 const double phi = atan2(dir.getDY(), dir.getDZ())*(180.0/PI);
339
340 if (phi < 0.0){
341 return phi + 360.0;
342 }
343 else{
344 return phi;
345 }
346 }
347
348
349 /**
350 * Get rotation over Y axis in Geant4 coordinate system
351 *
352 * \param dir direction
353 * \return Y-rotation [deg]
354 */
355 inline double GetYrotationG4(const JVersor3D& dir)
356 {
357 using namespace JPP;
358
359 return asin(-dir.getDX())*(180.0/PI);
360 }
361
362
363 inline void read_gdml(std::istream&, JDetector&)
364 {
365 THROW(JException, "Operation not defined.");
366 }
367
368
369 /**
370 * Writes KM3Sim GDML input file from detector
371 *
372 * \param out output stream
373 * \param detector detector
374 */
375 inline void write_gdml(std::ostream& out, const JDetector& detector)
376 {
377 using namespace std;
378 using namespace JPP;
379
380 const double DEFAULT_CAN_MARGIN_M = 350.0; // default can margin [m]
381 const double DEFAULT_WORLD_MARGIN_M = 50.0; // default world margin [m]
382
383 const JCylinder3D cylinder(detector.begin(), detector.end());
384
385 double can_margin;
386
387 if (CAN_MARGIN_M) {
388 can_margin = atof(CAN_MARGIN_M);
389 } else {
390 cerr << "CAN_MARGIN_M not defined! Setting standard CAN_MARGIN_M " << DEFAULT_CAN_MARGIN_M << " m." << endl;
391 can_margin = DEFAULT_CAN_MARGIN_M; //this is given in meters like all the dimensions in the GDML file (look at the unit field of every position and solid definition)
392 }
393
394 const double WorldCylinderHeight = 2*(cylinder.getZmax() - cylinder.getZmin() + can_margin + DEFAULT_WORLD_MARGIN_M);
395 const double WorldRadius = cylinder.getLength() + cylinder.getRadius() + can_margin + DEFAULT_WORLD_MARGIN_M;
396
397 const double Crust_Z_size = WorldCylinderHeight/2;
398 const double Crust_Z_position = -WorldCylinderHeight/4;
399
400 out << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<gdml xmlns:gdml=\"http://cern.ch/2001/Schemas/GDML\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"";
401 if (!GDML_SCHEMA) {
402 cerr << "GDML_SCHEMA_DIR NOT DEFINED! Setting default path." << endl;
403 out << G4GDML_DEFAULT_SCHEMALOCATION << "\">\n\n\n";
404 } else {
405 out << GDML_SCHEMA << "gdml.xsd\">\n\n\n";
406 }
407 out << "<!-- Jpp version: "<< getGITVersion() << " -->\n";
408 out << "<define>\n";
409 out << "<rotation name=\"identity\"/>\n<position name=\"zero\"/>\n";
410
411 int PMTs_NO = 0;
412
413 for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
414
415 if(module->empty()) continue;
416
417 const JVector3D center = module->getCenter();
418
419 out << "<position name=\"PosString" << module->getString() << "_Dom" << module->getID() << "\" unit=\"m\" x=\"" << module->getX() << "\" y=\"" << module->getY() << "\" z=\"" << module->getZ() << "\"/>\n";
420
421 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
422
423 const JVector3D vec = static_cast<JVector3D>(*pmt).sub(center);
424 out << "<position name=\"CathodPosition" << pmt->getID() << "_" << module->getID() << "\" unit=\"m\" x=\"" << vec.getX() << "\" y=\"" << vec.getY() << "\" z=\"" << vec.getZ() << "\"/>\n";
425 out << "<rotation name=\"CathodRotation" << pmt->getID() << "_" << module->getID() << "\" unit=\"deg\" x=\"" << GetXrotationG4(*pmt) << "\" y=\"" << GetYrotationG4(*pmt) << "\" z=\"0.000000\"/>\n";
426 out << "<constant name=\"CathodID_" << PMTs_NO << "\" value=\"" << pmt->getID() << "\"/>\n";
427 PMTs_NO++;
428 }
429
430 }
431
432 out << "<position name=\"OMShift\" unit=\"m\" x=\"0\" y=\"0\" z=\"0.0392\"/>\n";
433 out << "\n\n\n";
434 out << "<!-- end of DU position definitions -->\n<position name=\"CrustPosition\" unit=\"m\" x=\"0\" y=\"0\" z=\"" << Crust_Z_position << "\"/>\n";
435
436 out << "</define>\n";
437 out << "<materials>\n";
438 out << "</materials>\n";
439 out << "<solids>\n";
440 out << " <box name=\"CrustBox\" lunit=\"m\" x=\"2200\" y=\"2200\" z=\"" << Crust_Z_size << "\"/>\n";
441 out << " <box name=\"StoreyBox\" lunit=\"m\" x=\"0.6\" y=\"0.6\" z=\"0.6\"/>\n";
442 out << " <sphere name=\"OMSphere\" lunit=\"cm\" aunit=\"deg\" rmin=\"0.0\" rmax=\"21.6\" startphi=\"0.0\" deltaphi=\"360.0\" starttheta=\"0.0\" deltatheta=\"180.0\"/>\n";
443 out << " <tube name=\"CathodTube\" lunit=\"cm\" aunit=\"deg\" rmin=\"0.0\" rmax=\"4.7462\" z=\"0.5\" startphi=\"0.0\" deltaphi=\"360.0\"/>\n";
444 out << " <tube name=\"WorldTube\" lunit=\"m\" aunit=\"deg\" rmin=\"0.0\" rmax=\"" << WorldRadius << "\" z=\"" << WorldCylinderHeight << "\" startphi=\"0.0\" deltaphi=\"360.0\"/>\n";
445 out << "</solids>\n\n\n";
446
447 out << "<structure>\n";
448 out << " <volume name=\"CathodVolume\">\n";
449 out << " <materialref ref=\"Cathod\"/>\n";
450 out << " <solidref ref=\"CathodTube\"/>\n";
451 out << " </volume>\n";
452
453 out << "<!-- OMVolume(s) construction -->\n";
454
455 for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
456
457 if(module->empty()) continue;
458 out << " <volume name=\"OMVolume" << module->getID() << "\">\n";
459 out << " <materialref ref=\"Water\"/>\n";
460 out << " <solidref ref=\"OMSphere\"/>\n";
461
462 for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
463 out << " <physvol>\n";
464 out << " <volumeref ref=\"CathodVolume\"/>\n";
465 out << " <positionref ref=\"CathodPosition" << pmt->getID() << "_" << module->getID() << "\"/>\n";
466 out << " <rotationref ref=\"CathodRotation" << pmt->getID() << "_" << module->getID() << "\"/>\n";
467 out << " </physvol>\n";
468 }
469
470 out << " </volume>\n";
471 }
472
473 out << "<!-- StoreyVolume(s) construction -->\n";
474
475 for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
476 if(module->empty()) continue;
477 out << " <volume name=\"StoreyVolume" << module->getID() << "\">\n";
478 out << " <materialref ref=\"Water\"/>\n";
479 out << " <solidref ref=\"StoreyBox\"/>\n";
480 out << " <physvol>\n";
481 out << " <volumeref ref=\"OMVolume" << module->getID() << "\"/>\n";
482 out << " <positionref ref=\"OMShift\"/>\n";
483 out << " <rotationref ref=\"identity\"/>\n";
484 out << " </physvol>\n";
485 out << " </volume>\n";
486 }
487
488 out << "<!-- Crust Volume construction-->\n";
489 out << "<volume name=\"CrustVolume\">\n";
490 out << " <materialref ref=\"Crust\"/>\n";
491 out << " <solidref ref=\"CrustBox\"/>\n";
492 out << "</volume>\n";
493
494 out << "<!-- World Volume construction-->\n";
495 out << "<volume name=\"WorldVolume\">\n";
496 out << " <materialref ref=\"Water\"/>\n";
497 out << " <solidref ref=\"WorldTube\"/>\n";
498
499 out << " <physvol>\n";
500 out << " <volumeref ref=\"CrustVolume\"/>\n";
501 out << " <positionref ref=\"CrustPosition\"/>\n";
502 out << " <rotationref ref=\"identity\"/>\n";
503 out << " </physvol>\n";
504
505 for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
506 if(module->empty()) continue;
507 out << " <physvol>\n";
508 out << " <volumeref ref=\"StoreyVolume" << module->getID() << "\"/>\n";
509 out << " <positionref ref=\"PosString" << module->getString() << "_Dom" << module->getID() << "\"/>\n";
510 out << " <rotationref ref=\"identity\"/>\n";
511 out << " </physvol>\n";
512 }
513
514 out << "</volume>\n";
515
516 out << "</structure>\n";
517 out << "<setup name=\"Default\" version=\"1.0\">\n";
518 out << "<world ref=\"WorldVolume\"/>\n";
519 out << "</setup>\n";
520 out << "</gdml>\n";
521 }
522
523
524 /**
525 * Load detector from input file.
526 *
527 * Supported file formats:
528 * - ASCII file, extension JDETECTOR::GENDET_DETECTOR_FILE_FORMAT, gendet format;
529 * - binary file, extension JDETECTOR::BINARY_DETECTOR_FILE_FORMAT, Jpp internal format;
530 * - ASCII file, extension JDETECTOR::KM3NET_DETECTOR_FILE_FORMAT, %KM3NeT standard format;
531 * - gzipped file, extension JDETECTOR::ZIPPED_DETECTOR_FILE_FORMAT, %KM3NeT standard format;
532 *
533 * \param file_name file name
534 * \param detector detector
535 */
536 inline void load(const std::string& file_name, JDetector& detector)
537 {
538 using namespace std;
539 using namespace JPP;
540
541 if (getFilenameExtension(file_name) == GENDET_DETECTOR_FILE_FORMAT) {
542
543 JMonteCarloDetector buffer(true);
544
545 ifstream in(file_name.c_str());
546
547 if (!in) {
548 THROW(JFileOpenException, "File not opened for reading: " << file_name);
549 }
550
551 in >> buffer;
552
553 in.close();
554
555 detector.swap(buffer);
556
557 } else if (getFilenameExtension(file_name) == BINARY_DETECTOR_FILE_FORMAT[0] ||
558 getFilenameExtension(file_name) == BINARY_DETECTOR_FILE_FORMAT[1]) {
559
560 JFileStreamReader in(file_name.c_str());
561
562 if (!in) {
563 THROW(JFileOpenException, "File not opened for reading: " << file_name);
564 }
565
566 try {
567
568 detector.read(in);
569
570 } catch(const exception& error) {
571
572 // recovery procedure for old format of comments
573
575
576 in.clear();
577 in.rewind();
578
579 detector.read(in);
580
582 }
583
584 in.close();
585
586 } else if (getFilenameExtension(file_name) == KM3NET_DETECTOR_FILE_FORMAT) {
587
588 ifstream in(file_name.c_str());
589
590 if (!in) {
591 THROW(JFileOpenException, "File not opened for reading: " << file_name);
592 }
593
594 in >> detector;
595
596 in.close();
597
598 } else if (getFilenameExtension(file_name) == ZIPPED_DETECTOR_FILE_FORMAT) {
599
600 igzstream in(file_name.c_str());
601
602 if (!in) {
603 THROW(JFileOpenException, "File not opened for reading: " << file_name);
604 }
605
606 in >> detector;
607
608 in.close();
609
610 } else {
611
612 THROW(JProtocolException, "Protocol not defined: " << file_name);
613 }
614
615 if (!detector.hasVersion()) {
616 THROW(JValueOutOfRange, "Invalid version <" << detector.getVersion() << ">");
617 }
618 }
619
620
621 /**
622 * Store detector to output file.
623 *
624 * Supported file formats:
625 * - binary file, extension JDETECTOR::BINARY_DETECTOR_FILE_FORMAT, Jpp internal format;
626 * - ASCII file, extension JDETECTOR::KM3NET_DETECTOR_FILE_FORMAT, %KM3NeT standard format;
627 * - gzipped file, extension JDETECTOR::ZIPPED_DETECTOR_FILE_FORMAT, %KM3NeT standard format;
628 * - gdml file, extension JDETECTOR::GDML_DETECTOR_FILE_FORMAT, KM3Sim input format;
629 *
630 * \param file_name file name
631 * \param detector detector
632 */
633 inline void store(const std::string& file_name, const JDetector& detector)
634 {
635 using namespace std;
636 using namespace JPP;
637
638 if (getFilenameExtension(file_name) == BINARY_DETECTOR_FILE_FORMAT[1]) {
639
640 JFileStreamWriter out(file_name.c_str());
641
642 if (!out) {
643 THROW(JFileOpenException, "File not opened for writing: " << file_name);
644 }
645
646 detector.write(out);
647
648 out.close();
649
650 } else if (getFilenameExtension(file_name) == KM3NET_DETECTOR_FILE_FORMAT) {
651
652 std::ofstream out(file_name.c_str());
653
654 if (!out) {
655 THROW(JFileOpenException, "File not opened for writing: " << file_name);
656 }
657
658 out << detector;
659
660 out.close();
661
662 } else if (getFilenameExtension(file_name) == ZIPPED_DETECTOR_FILE_FORMAT) {
663
664 ogzstream out(file_name.c_str());
665
666 if (!out) {
667 THROW(JFileOpenException, "File not opened for writing: " << file_name);
668 }
669
670 out << detector;
671
672 out.close();
673
674 } else if (getFilenameExtension(file_name) == GDML_DETECTOR_FILE_FORMAT) {
675
676 std::ofstream out(file_name.c_str());
677
678 if (!out) {
679 THROW(JFileOpenException, "File not opened for writing: " << file_name);
680 }
681
682 write_gdml(out, detector);
683
684 out.close();
685
686 } else {
687
688 THROW(JProtocolException, "Protocol not defined: " << file_name);
689 }
690 }
691
692
693 /**
694 * Auxiliary class to get rotation matrix between two optical modules.
695 */
696 struct JRotation :
697 public JRotation3D
698 {
699
700 static const size_t NUMBER_OF_DIMENSIONS = 3; //!< Number of dimensions
701
702
703 /**
704 * Get rotation matrix to go from first to second module.
705 *
706 * \param first first module
707 * \param second second module
708 * \return rotation matrix
709 */
710 const JRotation3D& operator()(const JModule& first, const JModule& second)
711 {
712 this->setIdentity();
713
714 if (first.size() == second.size()) {
715
716 const size_t N = first.size();
717
718 if (N >= NUMBER_OF_DIMENSIONS) {
719
720 in .resize(N);
721 out.resize(N);
722
723 for (size_t i = 0; i != N; ++i) {
724 in [i] = first .getPMT(i).getDirection();
725 out[i] = second.getPMT(i).getDirection();
726 }
727
728 for (size_t i = 0; i != NUMBER_OF_DIMENSIONS; ++i) {
729 if (!orthonormalise(i)) {
730 THROW(JException, "Failure to orthonormalise direction " << i);
731 }
732 }
733
734 this->a00 = out[0].getX() * in[0].getX() + out[1].getX() * in[1].getX() + out[2].getX() * in[2].getX();
735 this->a01 = out[0].getX() * in[0].getY() + out[1].getX() * in[1].getY() + out[2].getX() * in[2].getY();
736 this->a02 = out[0].getX() * in[0].getZ() + out[1].getX() * in[1].getZ() + out[2].getX() * in[2].getZ();
737
738 this->a10 = out[0].getY() * in[0].getX() + out[1].getY() * in[1].getX() + out[2].getY() * in[2].getX();
739 this->a11 = out[0].getY() * in[0].getY() + out[1].getY() * in[1].getY() + out[2].getY() * in[2].getY();
740 this->a12 = out[0].getY() * in[0].getZ() + out[1].getY() * in[1].getZ() + out[2].getY() * in[2].getZ();
741
742 this->a20 = out[0].getZ() * in[0].getX() + out[1].getZ() * in[1].getX() + out[2].getZ() * in[2].getX();
743 this->a21 = out[0].getZ() * in[0].getY() + out[1].getZ() * in[1].getY() + out[2].getZ() * in[2].getY();
744 this->a22 = out[0].getZ() * in[0].getZ() + out[1].getZ() * in[1].getZ() + out[2].getZ() * in[2].getZ();
745
746 } else {
747
748 THROW(JException, "Module " << first.getID() << " size " << N << " < " << NUMBER_OF_DIMENSIONS);
749 }
750
751 } else {
752
753 THROW(JException, "Module " << first.getID() << " size " << first.size() << " != " << second.size());
754 }
755
756 return *this;
757 }
758
759 private:
760 /**
761 * Put normalised primary direction at specified index and orthoganilise following directions.\n
762 * This procedure follows Gram-Schmidt process.
763 *
764 * \param index index
765 * \param precision precision
766 * \return true if primary direction exists; else false
767 */
768 bool orthonormalise(const size_t index, const double precision = std::numeric_limits<double>::epsilon())
769 {
770 using namespace std;
771
772 size_t pos = index;
773
774 for (size_t i = index + 1; i != in.size(); ++i) {
775 if (in[i].getLengthSquared() > in[pos].getLengthSquared()) {
776 pos = i;
777 }
778 }
779
780 const double u = in[pos].getLength();
781
782 if (u > precision) {
783
784 in [pos] /= u;
785 out[pos] /= u;
786
787 if (pos != index) {
788 swap(in [pos], in [index]);
789 swap(out[pos], out[index]);
790 }
791
792 for (size_t i = index + 1; i != in.size(); ++i) {
793
794 const double dot = in[index].getDot(in[i]);
795
796 in [i] -= dot * in [index];
797 out[i] -= dot * out[index];
798 }
799
800 return true;
801
802 } else {
803
804 return false;
805 }
806 }
807
808
811 };
812
813
814 /**
815 * Function object to get rotation matrix to go from first to second module.
816 */
818
819
820 /**
821 * Get position to go from first to second module.
822 *
823 * \param first first module
824 * \param second second module
825 * \return position
826 */
827 inline JPosition3D getPosition(const JModule& first, const JModule& second)
828 {
829 return second.getPosition() - first.getPosition();
830 }
831
832
833 /**
834 * Get calibration to go from first to second calibration.
835 *
836 * \param first first calibration
837 * \param second second calibration
838 * \return calibration
839 */
840 inline JCalibration getCalibration(const JCalibration& first, const JCalibration& second)
841 {
842 return JCalibration(second.getT0() - first.getT0());
843 }
844}
845
846#endif
Data structure for detector geometry and calibration.
Exceptions.
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Logical location of module.
I/O manipulators.
Binary methods for member methods.
Mathematical constants.
Physics constants.
Auxiliary class to define a range between two values.
Auxiliary methods for handling file names, type names and environment.
Jpp environment information.
Data structure for time calibration.
double getT0() const
Get time offset.
Detector data structure.
Definition JDetector.hh:96
static void setStartOfComment(const start_of_comment_type option)
Set option for short start of comment in binary I/O.
Definition JDetector.hh:589
Data structure for a composite optical module.
Definition JModule.hh:75
const JPMT & getPMT(const int index) const
Get PMT.
Definition JModule.hh:172
Monte Carlo detector (i.e. ".det" file).
double getRadius() const
Get radius.
Definition JCircle2D.hh:144
double getLength() const
Get length.
Definition JVector2D.hh:199
double getZmin() const
Get minimal z position.
double getZmax() const
Get maximal z position.
const JDirection3D & getDirection() const
Get direction.
Data structure for position in three dimensions.
const JPosition3D & getPosition() const
Get position.
Data structure for vector in three dimensions.
Definition JVector3D.hh:36
JVector3D & sub(const JVector3D &vector)
Subtract vector.
Definition JVector3D.hh:158
Data structure for normalised vector in three dimensions.
Definition JVersor3D.hh:28
double getDY() const
Get y direction.
Definition JVersor3D.hh:106
double getDX() const
Get x direction.
Definition JVersor3D.hh:95
double getDZ() const
Get z direction.
Definition JVersor3D.hh:117
Binary buffered file input.
virtual void clear() override
Clear status of reader.
Binary buffered file output.
void close()
Close file.
General exception.
Definition JException.hh:24
Exception for opening of file.
int getID() const
Get identifier.
Definition JObjectID.hh:50
Protocol exception.
Exception for accessing a value in a collection that is outside of its range.
JMatrix3D & setIdentity()
Set to identity matrix.
static JRange< double, std::less< double > > DEFAULT_RANGE()
Definition JRange.hh:555
range_type & include(argument_type x)
Include given value to range.
Definition JRange.hh:397
T getLowerLimit() const
Get lower limit.
Definition JRange.hh:202
T getUpperLimit() const
Get upper limit.
Definition JRange.hh:213
void close()
Definition gzstream.h:185
file Auxiliary data structures and methods for detector calibration.
Definition JAnchor.hh:12
int getNumberOfPMTs(const JModule &module)
Get number of PMTs.
static JRotation getRotation
Function object to get rotation matrix to go from first to second module.
int getNumberOfFloors(const JDetector &detector)
Get number of floors.
floor_range getRangeOfFloors(const JDetector &detector)
Get range of floors.
void load(const std::string &file_name, JDetector &detector)
Load detector from input file.
static const char *const GDML_DETECTOR_FILE_FORMAT
KM3Sim input format.
JCalibration getCalibration(const JCalibration &first, const JCalibration &second)
Get calibration to go from first to second calibration.
void write_gdml(std::ostream &out, const JDetector &detector)
Writes KM3Sim GDML input file from detector.
void store(const std::string &file_name, const JDetector &detector)
Store detector to output file.
static const char *const ZIPPED_DETECTOR_FILE_FORMAT
zipped KM3NeT standard ASCII format
std::set< int > getStringIDs(const JDetector &detector)
Get list of strings identifiers.
static const char *const G4GDML_DEFAULT_SCHEMALOCATION
JPosition3D getPosition(const JModule &first, const JModule &second)
Get position to go from first to second module.
JTOOLS::JRange< int > floor_range
Type definition for range of floors.
double getMaximalTime(const JDetector &detector)
Get maximal time between optical modules in detector following causality.
static const char *const CAN_MARGIN_M
extension of the detector size to comply with the can definition
static const char *const KM3NET_DETECTOR_FILE_FORMAT
KM3NeT standard ASCII format
static const char *const GDML_SCHEMA
directory necessary for correct GDML header output
static const char *const GENDET_DETECTOR_FILE_FORMAT
File name extensions.
double GetYrotationG4(const JVersor3D &dir)
Get rotation over Y axis in Geant4 coordinate system.
int getNumberOfModules(const JDetector &detector, const bool option=false)
Get number of modules.
double getMinimalDistance(const JDetector &detector)
Get minimal distance between modules in detector.
double getMaximalDistance(const JDetector &detector, const bool option=false)
Get maximal distance between modules in detector.
double putTime(const T &t1, const JCalibration &cal)
Get de-calibrated time.
JTimeRange getTimeRange(const JTimeRange &timeRange, const JModule &module)
Get de-calibrated time range.
std::set< int > getModuleIDs(const JDetector &detector, const bool option=false)
Get list of modules identifiers.
double GetXrotationG4(const JVersor3D &dir)
Get rotation over X axis in Geant4 coordinate system.
void read_gdml(std::istream &, JDetector &)
static const char *const BINARY_DETECTOR_FILE_FORMAT[]
JIO binary file format.
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
Calibration.
Definition JHead.hh:330
Detector file.
Definition JHead.hh:227
Auxiliary class to get rotation matrix between two optical modules.
std::vector< JVector3D > out
const JRotation3D & operator()(const JModule &first, const JModule &second)
Get rotation matrix to go from first to second module.
std::vector< JVector3D > in
bool orthonormalise(const size_t index, const double precision=std::numeric_limits< double >::epsilon())
Put normalised primary direction at specified index and orthoganilise following directions.
static const size_t NUMBER_OF_DIMENSIONS
Number of dimensions.