Jpp  18.1.0
the software that should make you happy
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 
15 #include "JDetector/JDetector.hh"
17 #include "JDetector/JTimeRange.hh"
20 #include "JDetector/JLocation.hh"
23 #include "JGeometry3D/JVector3D.hh"
24 #include "JGeometry3D/JVersor3D.hh"
26 #include "JPhysics/JConstants.hh"
27 #include "JMath/JConstants.hh"
28 #include "JMath/JMathToolkit.hh"
29 #include "JTools/JRange.hh"
30 #include "JIO/JFileStreamIO.hh"
31 #include "Jeep/JeepToolkit.hh"
32 #include "JLang/JException.hh"
33 #include "JLang/gzstream.h"
34 #include "JLang/JManip.hh"
35 #include "JLang/Jpp.hh"
36 #include "JLang/JType.hh"
37 
38 
39 /**
40  * \author mdejong
41  */
42 
43 namespace JDETECTOR {}
44 namespace JPP { using namespace JDETECTOR; }
45 
46 /**
47  * Auxiliary classes and methods for detector calibration and simulation.
48  */
49 namespace JDETECTOR {
50 
51  using JLANG::JException;
54  using JLANG::JType;
55 
56 
57  /**
58  * File name extensions.
59  */
60  static const char* const GENDET_DETECTOR_FILE_FORMAT = "det"; //!< file format used by gendet
61  static const char* const BINARY_DETECTOR_FILE_FORMAT[] = { "dat", "datx" }; //!< JIO binary file format
62  static const char* const KM3NET_DETECTOR_FILE_FORMAT = "detx"; //!< %KM3NeT standard ASCII format
63  static const char* const ZIPPED_DETECTOR_FILE_FORMAT = "gz"; //!< zipped %KM3NeT standard ASCII format
64  static const char* const GDML_DETECTOR_FILE_FORMAT = "gdml"; //!< KM3Sim input format
65 
66  static const char* const GDML_SCHEMA = getenv("GDML_SCHEMA_DIR"); //!< directory necessary for correct GDML header output
67  static const char* const CAN_MARGIN_M = getenv("CAN_MARGIN_M"); //!< extension of the detector size to comply with the can definition
68  static const char* const G4GDML_DEFAULT_SCHEMALOCATION = "http://service-spi.web.cern.ch/service-spi/app/releases/GDML/schema/gdml.xsd";
69 
70 
71  /**
72  * Get maximal distance between modules in detector.
73  * The option can be used to include base modules, if any.
74  *
75  * \param detector detector
76  * \param option option
77  * \return maximal distance [m]
78  */
79  inline double getMaximalDistance(const JDetector& detector, const bool option = false)
80  {
81  using namespace JPP;
82 
83  double dmax = 0.0;
84 
85  for (JDetector::const_iterator i1 = detector.begin(); i1 != detector.end(); ++i1) {
86  for (JDetector::const_iterator i2 = detector.begin(); i2 != i1; ++i2) {
87 
88  if (option || (i1->getFloor() != 0 && i2->getFloor() != 0)) {
89 
90  const double ds = getDistance(i1->getPosition(), i2->getPosition());
91 
92  if (ds > dmax) {
93  dmax = ds;
94  }
95  }
96  }
97  }
98 
99  return dmax;
100  }
101 
102 
103  /**
104  * Get rotation over X axis in Geant4 coordinate system
105  *
106  * \param dir direction
107  * \return X-rotation [deg]
108  */
109  inline double GetXrotationG4(const JVersor3D dir)
110  {
111  using namespace JPP;
112 
113  const double phi = atan2(dir.getDY(), dir.getDZ())*(180.0/PI);
114 
115  if (phi < 0.0){
116  return phi + 360.0;
117  }
118  else{
119  return phi;
120  }
121  }
122 
123 
124  /**
125  * Get rotation over Y axis in Geant4 coordinate system
126  *
127  * \param dir direction
128  * \return Y-rotation [deg]
129  */
130  inline double GetYrotationG4(const JVersor3D dir)
131  {
132  using namespace JPP;
133 
134  return asin(-dir.getDX())*(180.0/PI);
135  }
136 
137 
138  inline void read_gdml(std::istream&, JDetector&)
139  {
140  THROW(JException, "Operation not defined.");
141  }
142 
143 
144  /**
145  * Writes KM3Sim GDML input file from detector
146  *
147  * \param out output stream
148  * \param detector detector
149  */
150  inline void write_gdml(std::ostream& out, const JDetector& detector)
151  {
152  using namespace std;
153  using namespace JPP;
154 
155  const double DEFAULT_CAN_MARGIN_M = 350.0; // default can margin [m]
156  const double DEFAULT_WORLD_MARGIN_M = 50.0; // default world margin [m]
157 
158  const JCylinder3D cylinder(detector.begin(), detector.end());
159 
160  double can_margin;
161 
162  if (CAN_MARGIN_M) {
163  can_margin = atof(CAN_MARGIN_M);
164  } else {
165  cerr << "CAN_MARGIN_M not defined! Setting standard CAN_MARGIN_M " << DEFAULT_CAN_MARGIN_M << " m." << endl;
166  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)
167  }
168 
169  const double WorldCylinderHeight = 2*(cylinder.getZmax() - cylinder.getZmin() + can_margin + DEFAULT_WORLD_MARGIN_M);
170  const double WorldRadius = cylinder.getLength() + cylinder.getRadius() + can_margin + DEFAULT_WORLD_MARGIN_M;
171 
172  const double Crust_Z_size = WorldCylinderHeight/2;
173  const double Crust_Z_position = -WorldCylinderHeight/4;
174 
175  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=\"";
176  if (!GDML_SCHEMA) {
177  cerr << "GDML_SCHEMA_DIR NOT DEFINED! Setting default path." << endl;
178  out << G4GDML_DEFAULT_SCHEMALOCATION << "\">\n\n\n";
179  } else {
180  out << GDML_SCHEMA << "gdml.xsd\">\n\n\n";
181  }
182  out << "<!-- Jpp version: "<< getGITVersion() << " -->\n";
183  out << "<define>\n";
184  out << "<rotation name=\"identity\"/>\n<position name=\"zero\"/>\n";
185 
186  int PMTs_NO = 0;
187 
188  for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
189 
190  if(module->empty()) continue;
191 
192  const JVector3D center = module->getCenter();
193 
194  out << "<position name=\"PosString" << module->getString() << "_Dom" << module->getID() << "\" unit=\"m\" x=\"" << module->getX() << "\" y=\"" << module->getY() << "\" z=\"" << module->getZ() << "\"/>\n";
195 
196  for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
197 
198  const JVector3D vec = static_cast<JVector3D>(*pmt).sub(center);
199  out << "<position name=\"CathodPosition" << pmt->getID() << "_" << module->getID() << "\" unit=\"m\" x=\"" << vec.getX() << "\" y=\"" << vec.getY() << "\" z=\"" << vec.getZ() << "\"/>\n";
200  out << "<rotation name=\"CathodRotation" << pmt->getID() << "_" << module->getID() << "\" unit=\"deg\" x=\"" << GetXrotationG4(*pmt) << "\" y=\"" << GetYrotationG4(*pmt) << "\" z=\"0.000000\"/>\n";
201  out << "<constant name=\"CathodID_" << PMTs_NO << "\" value=\"" << pmt->getID() << "\"/>\n";
202  PMTs_NO++;
203  }
204 
205  }
206 
207  out << "<position name=\"OMShift\" unit=\"m\" x=\"0\" y=\"0\" z=\"0.0392\"/>\n";
208  out << "\n\n\n";
209  out << "<!-- end of DU position definitions -->\n<position name=\"CrustPosition\" unit=\"m\" x=\"0\" y=\"0\" z=\"" << Crust_Z_position << "\"/>\n";
210 
211  out << "</define>\n";
212  out << "<materials>\n";
213  out << "</materials>\n";
214  out << "<solids>\n";
215  out << " <box name=\"CrustBox\" lunit=\"m\" x=\"2200\" y=\"2200\" z=\"" << Crust_Z_size << "\"/>\n";
216  out << " <box name=\"StoreyBox\" lunit=\"m\" x=\"0.6\" y=\"0.6\" z=\"0.6\"/>\n";
217  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";
218  out << " <tube name=\"CathodTube\" lunit=\"cm\" aunit=\"deg\" rmin=\"0.0\" rmax=\"4.7462\" z=\"0.5\" startphi=\"0.0\" deltaphi=\"360.0\"/>\n";
219  out << " <tube name=\"WorldTube\" lunit=\"m\" aunit=\"deg\" rmin=\"0.0\" rmax=\"" << WorldRadius << "\" z=\"" << WorldCylinderHeight << "\" startphi=\"0.0\" deltaphi=\"360.0\"/>\n";
220  out << "</solids>\n\n\n";
221 
222  out << "<structure>\n";
223  out << " <volume name=\"CathodVolume\">\n";
224  out << " <materialref ref=\"Cathod\"/>\n";
225  out << " <solidref ref=\"CathodTube\"/>\n";
226  out << " </volume>\n";
227 
228  out << "<!-- OMVolume(s) construction -->\n";
229 
230  for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
231 
232  if(module->empty()) continue;
233  out << " <volume name=\"OMVolume" << module->getID() << "\">\n";
234  out << " <materialref ref=\"Water\"/>\n";
235  out << " <solidref ref=\"OMSphere\"/>\n";
236 
237  for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
238  out << " <physvol>\n";
239  out << " <volumeref ref=\"CathodVolume\"/>\n";
240  out << " <positionref ref=\"CathodPosition" << pmt->getID() << "_" << module->getID() << "\"/>\n";
241  out << " <rotationref ref=\"CathodRotation" << pmt->getID() << "_" << module->getID() << "\"/>\n";
242  out << " </physvol>\n";
243  }
244 
245  out << " </volume>\n";
246  }
247 
248  out << "<!-- StoreyVolume(s) construction -->\n";
249 
250  for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
251  if(module->empty()) continue;
252  out << " <volume name=\"StoreyVolume" << module->getID() << "\">\n";
253  out << " <materialref ref=\"Water\"/>\n";
254  out << " <solidref ref=\"StoreyBox\"/>\n";
255  out << " <physvol>\n";
256  out << " <volumeref ref=\"OMVolume" << module->getID() << "\"/>\n";
257  out << " <positionref ref=\"OMShift\"/>\n";
258  out << " <rotationref ref=\"identity\"/>\n";
259  out << " </physvol>\n";
260  out << " </volume>\n";
261  }
262 
263  out << "<!-- Crust Volume construction-->\n";
264  out << "<volume name=\"CrustVolume\">\n";
265  out << " <materialref ref=\"Crust\"/>\n";
266  out << " <solidref ref=\"CrustBox\"/>\n";
267  out << "</volume>\n";
268 
269  out << "<!-- World Volume construction-->\n";
270  out << "<volume name=\"WorldVolume\">\n";
271  out << " <materialref ref=\"Water\"/>\n";
272  out << " <solidref ref=\"WorldTube\"/>\n";
273 
274  out << " <physvol>\n";
275  out << " <volumeref ref=\"CrustVolume\"/>\n";
276  out << " <positionref ref=\"CrustPosition\"/>\n";
277  out << " <rotationref ref=\"identity\"/>\n";
278  out << " </physvol>\n";
279 
280  for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
281  if(module->empty()) continue;
282  out << " <physvol>\n";
283  out << " <volumeref ref=\"StoreyVolume" << module->getID() << "\"/>\n";
284  out << " <positionref ref=\"PosString" << module->getString() << "_Dom" << module->getID() << "\"/>\n";
285  out << " <rotationref ref=\"identity\"/>\n";
286  out << " </physvol>\n";
287  }
288 
289  out << "</volume>\n";
290 
291  out << "</structure>\n";
292  out << "<setup name=\"Default\" version=\"1.0\">\n";
293  out << "<world ref=\"WorldVolume\"/>\n";
294  out << "</setup>\n";
295  out << "</gdml>\n";
296  }
297 
298 
299  /**
300  * Get maximal time between optical modules in detector following causality.
301  *
302  * \param detector detector
303  * \return maximal time [ns]
304  */
305  inline double getMaximalTime(const JDetector& detector)
306  {
307  using namespace JPP;
308 
310  }
311 
312 
313  /**
314  * Get maximal time between optical modules in detector following causality.
315  * The road width corresponds to the maximal distance traveled by the light.
316  *
317  * \param detector detector
318  * \param roadWidth_m road width [m]
319  * \return maximal time [ns]
320  */
321  inline double getMaximalTime(const JDetector& detector, const double roadWidth_m)
322  {
323  using namespace JPP;
324 
325  const double Dmax_m = getMaximalDistance(detector);
326 
327  return (sqrt((Dmax_m + roadWidth_m*getSinThetaC()) *
328  (Dmax_m - roadWidth_m*getSinThetaC())) +
329  roadWidth_m * getSinThetaC() * getTanThetaC()) * getInverseSpeedOfLight();
330  }
331 
332 
333  /**
334  * Get de-calibrated time range.
335  *
336  * The de-calibrated time range is corrected for minimal and maximal time offset of PMTs in given module.
337  *
338  * \param timeRange time range [ns]
339  * \param module module
340  * \return time range [ns]
341  */
342  inline JTimeRange getTimeRange(const JTimeRange& timeRange, const JModule& module)
343  {
344  if (!module.empty()) {
345 
347 
348  for (JModule::const_iterator pmt = module.begin(); pmt != module.end(); ++pmt) {
349 
350  const JCalibration& calibration = pmt->getCalibration();
351 
352  time_range.include(putTime(timeRange.getLowerLimit(), calibration));
353  time_range.include(putTime(timeRange.getUpperLimit(), calibration));
354  }
355 
356  return time_range;
357 
358  } else {
359 
360  return timeRange;
361  }
362  }
363 
364 
365  /**
366  * Get number of PMTs.
367  *
368  * \param module module
369  * \return number of PMTs
370  */
371  inline int getNumberOfPMTs(const JModule& module)
372  {
373  return module.size();
374  }
375 
376 
377  /**
378  * Get number of PMTs.
379  *
380  * \param detector detector
381  * \return number of PMTs
382  */
383  inline int getNumberOfPMTs(const JDetector& detector)
384  {
385  int number_of_pmts = 0;
386 
387  for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
388  number_of_pmts += getNumberOfPMTs(*module);
389  }
390 
391  return number_of_pmts;
392  }
393 
394 
395  /**
396  * Get list of strings identifiers.
397  *
398  * \param detector detector
399  * \return list of string identifiers
400  */
402  {
403  std::set<int> buffer;
404 
405  for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
406  buffer.insert(module->getString());
407  }
408 
409  return buffer;
410  }
411 
412 
413  /**
414  * Get number of floors.
415  *
416  * \param detector detector
417  * \return number of floors
418  */
420  {
421  std::set<int> buffer;
422 
423  for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
424  buffer.insert(module->getFloor());
425  }
426 
427  return buffer.size();
428  }
429 
430 
431  /**
432  * Type definition for range of floors.
433  */
435 
436 
437  /**
438  * Get range of floors.
439  *
440  * \param detector detector
441  * \return range of floors
442  */
443  inline floor_range getRangeOfFloors(const JDetector& detector)
444  {
445  floor_range buffer = floor_range::DEFAULT_RANGE();
446 
447  for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
448  buffer.include(module->getFloor());
449  }
450 
451  return buffer;
452  }
453 
454 
455  /**
456  * Get number of modules.
457  *
458  * \param detector detector
459  * \return number of modules
460  */
462  {
463  std::set<int> buffer;
464 
465  for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
466  buffer.insert(module->getID());
467  }
468 
469  return buffer.size();
470  }
471 
472 
473  /**
474  * Load detector from input file.
475  *
476  * Supported file formats:
477  * - ASCII file, extension JDETECTOR::GENDET_DETECTOR_FILE_FORMAT, gendet format;
478  * - binary file, extension JDETECTOR::BINARY_DETECTOR_FILE_FORMAT, Jpp internal format;
479  * - ASCII file, extension JDETECTOR::KM3NET_DETECTOR_FILE_FORMAT, %KM3NeT standard format;
480  * - gzipped file, extension JDETECTOR::ZIPPED_DETECTOR_FILE_FORMAT, %KM3NeT standard format;
481  *
482  * \param file_name file name
483  * \param detector detector
484  */
485  inline void load(const std::string& file_name, JDetector& detector)
486  {
487  using namespace std;
488  using namespace JPP;
489 
491 
492  JMonteCarloDetector buffer(true);
493 
494  ifstream in(file_name.c_str());
495 
496  if (!in) {
497  THROW(JFileOpenException, "File not opened for reading: " << file_name);
498  }
499 
500  in >> buffer;
501 
502  in.close();
503 
504  detector.swap(buffer);
505 
506  } else if (getFilenameExtension(file_name) == BINARY_DETECTOR_FILE_FORMAT[0] ||
508 
509  JFileStreamReader in(file_name.c_str());
510 
511  if (!in) {
512  THROW(JFileOpenException, "File not opened for reading: " << file_name);
513  }
514 
515  try {
516 
517  detector.read(in);
518 
519  } catch(const exception& error) {
520 
521  // recovery procedure for old format of comments
522 
524 
525  in.clear();
526  in.rewind();
527 
528  detector.read(in);
529 
531  }
532 
533  in.close();
534 
535  } else if (getFilenameExtension(file_name) == KM3NET_DETECTOR_FILE_FORMAT) {
536 
537  ifstream in(file_name.c_str());
538 
539  if (!in) {
540  THROW(JFileOpenException, "File not opened for reading: " << file_name);
541  }
542 
543  in >> detector;
544 
545  in.close();
546 
547  } else if (getFilenameExtension(file_name) == ZIPPED_DETECTOR_FILE_FORMAT) {
548 
549  igzstream in(file_name.c_str());
550 
551  if (!in) {
552  THROW(JFileOpenException, "File not opened for reading: " << file_name);
553  }
554 
555  in >> detector;
556 
557  in.close();
558 
559  } else {
560 
561  THROW(JProtocolException, "Protocol not defined: " << file_name);
562  }
563  }
564 
565 
566  /**
567  * Store detector to output file.
568  *
569  * Supported file formats:
570  * - binary file, extension JDETECTOR::BINARY_DETECTOR_FILE_FORMAT, Jpp internal format;
571  * - ASCII file, extension JDETECTOR::KM3NET_DETECTOR_FILE_FORMAT, %KM3NeT standard format;
572  * - gzipped file, extension JDETECTOR::ZIPPED_DETECTOR_FILE_FORMAT, %KM3NeT standard format;
573  * - gdml file, extension JDETECTOR::GDML_DETECTOR_FILE_FORMAT, KM3Sim input format;
574  *
575  * \param file_name file name
576  * \param detector detector
577  */
578  inline void store(const std::string& file_name, const JDetector& detector)
579  {
580  using namespace std;
581  using namespace JPP;
582 
583  if (getFilenameExtension(file_name) == BINARY_DETECTOR_FILE_FORMAT[1]) {
584 
585  JFileStreamWriter out(file_name.c_str());
586 
587  if (!out) {
588  THROW(JFileOpenException, "File not opened for writing: " << file_name);
589  }
590 
591  detector.write(out);
592 
593  out.close();
594 
595  } else if (getFilenameExtension(file_name) == KM3NET_DETECTOR_FILE_FORMAT) {
596 
597  std::ofstream out(file_name.c_str());
598 
599  if (!out) {
600  THROW(JFileOpenException, "File not opened for writing: " << file_name);
601  }
602 
603  out << detector;
604 
605  out.close();
606 
607  } else if (getFilenameExtension(file_name) == ZIPPED_DETECTOR_FILE_FORMAT) {
608 
609  ogzstream out(file_name.c_str());
610 
611  if (!out) {
612  THROW(JFileOpenException, "File not opened for writing: " << file_name);
613  }
614 
615  out << detector;
616 
617  out.close();
618 
619  } else if (getFilenameExtension(file_name) == GDML_DETECTOR_FILE_FORMAT) {
620 
621  std::ofstream out(file_name.c_str());
622 
623  if (!out) {
624  THROW(JFileOpenException, "File not opened for writing: " << file_name);
625  }
626 
627  write_gdml(out, detector);
628 
629  out.close();
630 
631  } else {
632 
633  THROW(JProtocolException, "Protocol not defined: " << file_name);
634  }
635  }
636 
637 
638  /**
639  * Get module according module address map.
640  *
641  * \param memo module address map
642  * \param id module identifier
643  * \param location module location
644  * \return module
645  */
646  inline const JModule& getModule(const JModuleAddressMap& memo,
647  const int id = -1,
648  const JLocation& location = JLocation())
649  {
650  static JModule module;
651 
652 
653  module.setID(id);
654 
655  module.setLocation(location);
656 
657  module.resize(memo.size());
658 
659  if (memo.has( 0)) { module[memo[ 0].tdc] = JPMT( 1, JAxis3D(JVector3D(+0.000, +0.000, -0.200), JVersor3D(+0.000, +0.000, -1.000))); }
660 
661  if (memo.has( 1)) { module[memo[ 1].tdc] = JPMT( 2, JAxis3D(JVector3D(+0.000, +0.105, -0.170), JVersor3D(+0.000, +0.527, -0.850))); }
662  if (memo.has( 2)) { module[memo[ 2].tdc] = JPMT( 3, JAxis3D(JVector3D(+0.091, +0.053, -0.170), JVersor3D(+0.456, +0.263, -0.850))); }
663  if (memo.has( 3)) { module[memo[ 3].tdc] = JPMT( 4, JAxis3D(JVector3D(+0.091, -0.053, -0.170), JVersor3D(+0.456, -0.263, -0.850))); }
664  if (memo.has( 4)) { module[memo[ 4].tdc] = JPMT( 5, JAxis3D(JVector3D(+0.000, -0.105, -0.170), JVersor3D(+0.000, -0.527, -0.850))); }
665  if (memo.has( 5)) { module[memo[ 5].tdc] = JPMT( 6, JAxis3D(JVector3D(-0.091, -0.053, -0.170), JVersor3D(-0.456, -0.263, -0.850))); }
666  if (memo.has( 6)) { module[memo[ 6].tdc] = JPMT( 7, JAxis3D(JVector3D(-0.091, +0.053, -0.170), JVersor3D(-0.456, +0.263, -0.850))); }
667 
668  if (memo.has( 7)) { module[memo[ 7].tdc] = JPMT( 8, JAxis3D(JVector3D(+0.083, +0.144, -0.111), JVersor3D(+0.416, +0.720, -0.555))); }
669  if (memo.has( 8)) { module[memo[ 8].tdc] = JPMT( 9, JAxis3D(JVector3D(+0.166, +0.000, -0.111), JVersor3D(+0.832, +0.000, -0.555))); }
670  if (memo.has( 9)) { module[memo[ 9].tdc] = JPMT(10, JAxis3D(JVector3D(+0.083, -0.144, -0.111), JVersor3D(+0.416, -0.720, -0.555))); }
671  if (memo.has(10)) { module[memo[10].tdc] = JPMT(11, JAxis3D(JVector3D(-0.083, -0.144, -0.111), JVersor3D(-0.416, -0.720, -0.555))); }
672  if (memo.has(11)) { module[memo[11].tdc] = JPMT(12, JAxis3D(JVector3D(-0.166, +0.000, -0.111), JVersor3D(-0.832, +0.000, -0.555))); }
673  if (memo.has(12)) { module[memo[12].tdc] = JPMT(13, JAxis3D(JVector3D(-0.083, +0.144, -0.111), JVersor3D(-0.416, +0.720, -0.555))); }
674 
675  if (memo.has(13)) { module[memo[13].tdc] = JPMT(14, JAxis3D(JVector3D(+0.000, +0.191, -0.059), JVersor3D(+0.000, +0.955, -0.295))); }
676  if (memo.has(14)) { module[memo[14].tdc] = JPMT(15, JAxis3D(JVector3D(+0.165, +0.096, -0.059), JVersor3D(+0.827, +0.478, -0.295))); }
677  if (memo.has(15)) { module[memo[15].tdc] = JPMT(16, JAxis3D(JVector3D(+0.165, -0.096, -0.059), JVersor3D(+0.827, -0.478, -0.295))); }
678  if (memo.has(16)) { module[memo[16].tdc] = JPMT(17, JAxis3D(JVector3D(+0.000, -0.191, -0.059), JVersor3D(+0.000, -0.955, -0.295))); }
679  if (memo.has(17)) { module[memo[17].tdc] = JPMT(18, JAxis3D(JVector3D(-0.165, -0.096, -0.059), JVersor3D(-0.827, -0.478, -0.295))); }
680  if (memo.has(18)) { module[memo[18].tdc] = JPMT(19, JAxis3D(JVector3D(-0.165, +0.096, -0.059), JVersor3D(-0.827, +0.478, -0.295))); }
681 
682  if (memo.has(19)) { module[memo[19].tdc] = JPMT(20, JAxis3D(JVector3D(+0.096, +0.165, +0.059), JVersor3D(+0.478, +0.827, +0.295))); }
683  if (memo.has(20)) { module[memo[20].tdc] = JPMT(21, JAxis3D(JVector3D(+0.191, +0.000, +0.059), JVersor3D(+0.955, +0.000, +0.295))); }
684  if (memo.has(21)) { module[memo[21].tdc] = JPMT(22, JAxis3D(JVector3D(+0.096, -0.165, +0.059), JVersor3D(+0.478, -0.827, +0.295))); }
685  if (memo.has(22)) { module[memo[22].tdc] = JPMT(23, JAxis3D(JVector3D(-0.096, -0.165, +0.059), JVersor3D(-0.478, -0.827, +0.295))); }
686  if (memo.has(23)) { module[memo[23].tdc] = JPMT(24, JAxis3D(JVector3D(-0.191, +0.000, +0.059), JVersor3D(-0.955, +0.000, +0.295))); }
687  if (memo.has(24)) { module[memo[24].tdc] = JPMT(25, JAxis3D(JVector3D(-0.096, +0.165, +0.059), JVersor3D(-0.478, +0.827, +0.295))); }
688 
689  if (memo.has(25)) { module[memo[25].tdc] = JPMT(26, JAxis3D(JVector3D(+0.000, +0.166, +0.111), JVersor3D(+0.000, +0.832, +0.555))); }
690  if (memo.has(26)) { module[memo[26].tdc] = JPMT(27, JAxis3D(JVector3D(+0.144, +0.083, +0.111), JVersor3D(+0.720, +0.416, +0.555))); }
691  if (memo.has(27)) { module[memo[27].tdc] = JPMT(28, JAxis3D(JVector3D(+0.144, -0.083, +0.111), JVersor3D(+0.720, -0.416, +0.555))); }
692  if (memo.has(28)) { module[memo[28].tdc] = JPMT(29, JAxis3D(JVector3D(+0.000, -0.166, +0.111), JVersor3D(+0.000, -0.832, +0.555))); }
693  if (memo.has(29)) { module[memo[29].tdc] = JPMT(30, JAxis3D(JVector3D(-0.144, -0.083, +0.111), JVersor3D(-0.720, -0.416, +0.555))); }
694  if (memo.has(30)) { module[memo[30].tdc] = JPMT(31, JAxis3D(JVector3D(-0.144, +0.083, +0.111), JVersor3D(-0.720, +0.416, +0.555))); }
695 
696  module.compile();
697 
698  module.set(JVector3D(0.0, 0.0, 0.0));
699 
700  return module;
701  }
702 
703 
704  /**
705  * Get module according given detector type.
706  *
707  * \param type detector type
708  * \param id module identifier
709  * \param location module location
710  * \return module
711  */
712  template<class JDetector_t>
713  inline const JModule& getModule(const JType<JDetector_t> type,
714  const int id,
715  const JLocation& location = JLocation())
716  {
717  return getModule(getModuleAddressMap<JDetector_t>(id), id, location);
718  }
719 
720 
721  /**
722  * Get module according Antares detector type.
723  *
724  * \param type Antares detector type
725  * \param id module identifier
726  * \param location module location
727  * \return module
728  */
729  inline const JModule& getModule(const JType<JAntares_t> type,
730  const int id,
731  const JLocation& location = JLocation())
732  {
733  static JModule module;
734 
735  module.setID(id);
736 
737  module.setLocation(location);
738 
739  if (module.empty()) {
740 
741  module.resize(3);
742 
743  const double R = 0.5; // [m]
744 
745  const double st = sin(0.75*PI);
746  const double ct = cos(0.75*PI);
747 
748  for (int i = 0; i != 3; ++i) {
749 
750  const double phi = (2.0*PI*i) / 3.0;
751  const double cp = cos(phi);
752  const double sp = sin(phi);
753 
754  module[i] = JPMT(i, JAxis3D(JVector3D(R*st*cp, R*st*sp, R*ct), JVersor3D(st*cp, st*sp, ct)));
755  }
756  }
757 
758  return module;
759  }
760 
761 
762  /**
763  * Get module according detector template.
764  *
765  * \param id module identifier
766  * \param location module location
767  * \return module
768  */
769  template<class JDetector_t>
770  inline const JModule& getModule(const int id,
771  const JLocation& location = JLocation())
772  {
773  return getModule(JType<JDetector_t>(), id, location);
774  }
775 
776 
777  /**
778  * Auxiliary class to get rotation matrix between two optical modules.
779  */
780  struct JRotation :
781  public JRotation3D
782  {
783 
784  static const size_t NUMBER_OF_DIMENSIONS = 3; //!< Number of dimensions
785 
786 
787  /**
788  * Get rotation matrix to go from first to second module.
789  *
790  * \param first first module
791  * \param second second module
792  * \return rotation matrix
793  */
794  const JRotation3D& operator()(const JModule& first, const JModule& second)
795  {
796  this->setIdentity();
797 
798  if (first.size() == second.size()) {
799 
800  const size_t N = first.size();
801 
802  if (N >= NUMBER_OF_DIMENSIONS) {
803 
804  in .resize(N);
805  out.resize(N);
806 
807  for (size_t i = 0; i != N; ++i) {
808  in [i] = first .getPMT(i).getDirection();
809  out[i] = second.getPMT(i).getDirection();
810  }
811 
812  for (size_t i = 0; i != NUMBER_OF_DIMENSIONS; ++i) {
813  if (!orthonormalise(i)) {
814  THROW(JException, "Failure to orthonormalise direction " << i);
815  }
816  }
817 
818  this->a00 = out[0].getX() * in[0].getX() + out[1].getX() * in[1].getX() + out[2].getX() * in[2].getX();
819  this->a01 = out[0].getX() * in[0].getY() + out[1].getX() * in[1].getY() + out[2].getX() * in[2].getY();
820  this->a02 = out[0].getX() * in[0].getZ() + out[1].getX() * in[1].getZ() + out[2].getX() * in[2].getZ();
821 
822  this->a10 = out[0].getY() * in[0].getX() + out[1].getY() * in[1].getX() + out[2].getY() * in[2].getX();
823  this->a11 = out[0].getY() * in[0].getY() + out[1].getY() * in[1].getY() + out[2].getY() * in[2].getY();
824  this->a12 = out[0].getY() * in[0].getZ() + out[1].getY() * in[1].getZ() + out[2].getY() * in[2].getZ();
825 
826  this->a20 = out[0].getZ() * in[0].getX() + out[1].getZ() * in[1].getX() + out[2].getZ() * in[2].getX();
827  this->a21 = out[0].getZ() * in[0].getY() + out[1].getZ() * in[1].getY() + out[2].getZ() * in[2].getY();
828  this->a22 = out[0].getZ() * in[0].getZ() + out[1].getZ() * in[1].getZ() + out[2].getZ() * in[2].getZ();
829 
830  } else {
831 
832  THROW(JException, "Module " << first.getID() << " size " << N << " < " << NUMBER_OF_DIMENSIONS);
833  }
834 
835  } else {
836 
837  THROW(JException, "Module " << first.getID() << " size " << first.size() << " != " << second.size());
838  }
839 
840  return *this;
841  }
842 
843  private:
844  /**
845  * Put normalised primary direction at specified index and orthoganilise following directions.\n
846  * This procedure follows Gram-Schmidt process.
847  *
848  * \param index index
849  * \param precision precision
850  * \return true if primary direction exists; else false
851  */
852  bool orthonormalise(const size_t index, const double precision = std::numeric_limits<double>::epsilon())
853  {
854  using namespace std;
855 
856  size_t pos = index;
857 
858  for (size_t i = index + 1; i != in.size(); ++i) {
859  if (in[i].getLengthSquared() > in[pos].getLengthSquared()) {
860  pos = i;
861  }
862  }
863 
864  const double u = in[pos].getLength();
865 
866  if (u > precision) {
867 
868  in [pos] /= u;
869  out[pos] /= u;
870 
871  if (pos != index) {
872  swap(in [pos], in [index]);
873  swap(out[pos], out[index]);
874  }
875 
876  for (size_t i = index + 1; i != in.size(); ++i) {
877 
878  const double dot = in[index].getDot(in[i]);
879 
880  in [i] -= dot * in [index];
881  out[i] -= dot * out[index];
882  }
883 
884  return true;
885 
886  } else {
887 
888  return false;
889  }
890  }
891 
892 
895  };
896 
897 
898  /**
899  * Function object to get rotation matrix to go from first to second module.
900  */
902 
903 
904  /**
905  * Get position to go from first to second module.
906  *
907  * \param first first module
908  * \param second second module
909  * \return position
910  */
911  inline JPosition3D getPosition(const JModule& first, const JModule& second)
912  {
913  return second.getPosition() - first.getPosition();
914  }
915 
916 
917  /**
918  * Get calibration to go from first to second calibration.
919  *
920  * \param first first calibration
921  * \param second second calibration
922  * \return calibration
923  */
925  {
926  return JCalibration(second.getT0() - first.getT0());
927  }
928 }
929 
930 #endif
Exception for opening of file.
Definition: JException.hh:358
double GetYrotationG4(const JVersor3D dir)
Get rotation over Y axis in Geant4 coordinate system.
General exception.
Definition: JException.hh:24
Exceptions.
T getLowerLimit() const
Get lower limit.
Definition: JRange.hh:202
Auxiliary methods for geometrical methods.
Data structure for a composite optical module.
Definition: JModule.hh:68
range_type & include(argument_type x)
Include given value to range.
Definition: JRange.hh:397
void setLocation(const JLocation &location)
Set location.
Definition: JLocation.hh:91
const JCalibration & getCalibration() const
Get calibration.
double getIndexOfRefraction()
Get average index of refraction of water corresponding to group velocity.
Detector data structure.
Definition: JDetector.hh:89
const JDirection3D & getDirection() const
Get direction.
Rotation matrix.
Definition: JRotation3D.hh:111
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Definition: JException.hh:712
std::set< int > getStringIDs(const JDetector &detector)
Get list of strings identifiers.
JTOOLS::JRange< int > floor_range
Type definition for range of floors.
int getNumberOfPMTs(const JModule &module)
Get number of PMTs.
static void setStartOfComment(const start_of_comment_type option)
Set option for short start of comment in binary I/O.
Definition: JDetector.hh:589
static JRotation getRotation
Function object to get rotation matrix to go from first to second module.
JCalibration getCalibration(const JCalibration &first, const JCalibration &second)
Get calibration to go from first to second calibration.
Jpp environment information.
static const char *const BINARY_DETECTOR_FILE_FORMAT[]
JIO binary file format.
Data structure for time calibration.
Auxiliary class for a type holder.
Definition: JType.hh:19
void read_gdml(std::istream &, JDetector &)
static const char *const GDML_SCHEMA
directory necessary for correct GDML header output
static const JModuleCounter getNumberOfModules
Function object to count unique modules.
static const char *const CAN_MARGIN_M
extension of the detector size to comply with the can definition
floor_range getRangeOfFloors(const JDetector &detector)
Get range of floors.
Data structure for detector geometry and calibration.
then echo The file $DIR KM3NeT_00000001_00000000 root already please rename or remove it first
double getDistance(const JFirst_t &first, const JSecond_t &second)
Get distance between objects.
JTimeRange getTimeRange(const Evt &event)
Get time range (i.e. time between earliest and latest hit) of Monte Carlo event.
Axis object.
Definition: JAxis3D.hh:38
then usage set_variable ACOUSTICS_WORKDIR $WORKDIR set_variable FORMULA sin([0]+2 *$PI *([1]+[2]*x)*x)" set_variable DY 1.0e-8 mkdir $WORKDIR for DETECTOR in $DETECTORS[*]
Monte Carlo detector (i.e. so-called .det file).
Lookup table for PMT addresses in optical module.
double putTime(const T &t1, const JCalibration &cal)
Get de-calibrated time.
JVector3D & sub(const JVector3D &vector)
Subtract vector.
Definition: JVector3D.hh:158
Detector specific mapping between logical positions and readout channels of PMTs in optical modules...
virtual JReader & read(JReader &in) override
Read from input.
Definition: JDetector.hh:473
std::string getGITVersion(const std::string &tag)
Get GIT version for given GIT tag.
Data structure for vector in three dimensions.
Definition: JVector3D.hh:34
virtual JWriter & write(JWriter &out) const override
Write to output.
Definition: JDetector.hh:523
Logical location of module.
Definition: JLocation.hh:37
Mathematical constants.
double getDY() const
Get y direction.
Definition: JVersor3D.hh:106
Auxiliary class to get rotation matrix between two optical modules.
double getDX() const
Get x direction.
Definition: JVersor3D.hh:95
Auxiliary methods for handling file names, type names and environment.
int getID() const
Get identifier.
Definition: JObjectID.hh:50
Data structure for PMT geometry, calibration and status.
Definition: JPMT.hh:43
void compile()
Compile module data.
Definition: JModule.hh:282
void store(const std::string &file_name, const JDetector &detector)
Store detector to output file.
JPosition3D getPosition(const Vec &pos)
Get position.
T getUpperLimit() const
Get upper limit.
Definition: JRange.hh:213
int getNumberOfFloors(const JDetector &detector)
Get number of floors.
then awk string
Physics constants.
static const double PI
Mathematical constants.
double getY() const
Get y position.
Definition: JVector3D.hh:104
const JPosition3D & getPosition() const
Get position.
Definition: JPosition3D.hh:130
double getMaximalTime(const double R_Hz)
Get maximal time for given rate.
const JPMT & getPMT(const int index) const
Get PMT.
Definition: JModule.hh:173
Logical location of module.
Protocol exception.
Definition: JException.hh:664
const JRotation3D & operator()(const JModule &first, const JModule &second)
Get rotation matrix to go from first to second module.
std::vector< JVector3D > in
I/O manipulators.
static const char *const KM3NET_DETECTOR_FILE_FORMAT
KM3NeT standard ASCII format
static const char *const ZIPPED_DETECTOR_FILE_FORMAT
zipped KM3NeT standard ASCII format
then JCookie sh JDataQuality D $DETECTOR_ID R
Definition: JDataQuality.sh:41
static const char *const GENDET_DETECTOR_FILE_FORMAT
File name extensions.
then usage $script< input file >[option[primary[working directory]]] nWhere option can be N
Definition: JMuonPostfit.sh:40
void load(const std::string &file_name, JDetector &detector)
Load detector from input file.
Auxiliary class to define a range between two values.
std::string getFilenameExtension(const std::string &file_name)
Get file name extension, i.e. part after last JEEP::FILENAME_SEPARATOR if any.
Definition: JeepToolkit.hh:109
const double getInverseSpeedOfLight()
Get inverse speed of light.
void setID(const int id)
Set identifier.
Definition: JObjectID.hh:72
double getX() const
Get x position.
Definition: JVector3D.hh:94
double getMaximalDistance(const JDetector &detector, const bool option=false)
Get maximal distance between modules in detector.
static const char *const G4GDML_DEFAULT_SCHEMALOCATION
then cp
double getTanThetaC()
Get average tangent of Cherenkov angle of water corresponding to group velocity.
Data structure for position in three dimensions.
Definition: JPosition3D.hh:36
static JRange< double, std::less< double > > DEFAULT_RANGE()
Default range.
Definition: JRange.hh:555
do set_variable DETECTOR_TXT $WORKDIR detector
Data structure for normalised vector in three dimensions.
Definition: JVersor3D.hh:26
double u[N+1]
Definition: JPolint.hh:776
then fatal Wrong number of arguments fi set_variable DETECTOR $argv[1] set_variable INPUT_FILE $argv[2] eval JPrintDetector a $DETECTOR O IDENTIFIER eval JPrintDetector a $DETECTOR O SUMMARY JAcoustics sh $DETECTOR_ID source JAcousticsToolkit sh CHECK_EXIT_CODE typeset A EMITTERS get_tripods $WORKDIR tripod txt EMITTERS get_transmitters $WORKDIR transmitter txt EMITTERS for EMITTER in
Definition: JCanberra.sh:46
JModule & set(const JVector3D &pos)
Set position.
Definition: JModule.hh:408
double GetXrotationG4(const JVersor3D dir)
Get rotation over X axis in Geant4 coordinate system.
static const char *const GDML_DETECTOR_FILE_FORMAT
KM3Sim input format.
double getZ() const
Get z position.
Definition: JVector3D.hh:115
bool has(const int index) const
Test whether index is available.
double getDZ() const
Get z direction.
Definition: JVersor3D.hh:117
std::vector< JVector3D > out
const double epsilon
Definition: JQuadrature.cc:21
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.
const JModule & getModule(const JDetector &detector, const JModuleLocation &location)
find module with a given string and floor number
double getSinThetaC()
Get average sine of Cherenkov angle of water corresponding to group velocity.
void write_gdml(std::ostream &out, const JDetector &detector)
Writes KM3Sim GDML input file from detector.
double getT0() const
Get time offset.