Jpp - 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"
19 #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 "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 
41 namespace JDETECTOR {}
42 namespace JPP { using namespace JDETECTOR; }
43 
44 /**
45  * Auxiliary classes and methods for detector calibration and simulation.
46  */
47 namespace JDETECTOR {
48 
49  using JLANG::JException;
52 
53 
54  /**
55  * File name extensions.
56  */
57  static const char* const GENDET_DETECTOR_FILE_FORMAT = "det"; //!< file format used by gendet
58  static const char* const BINARY_DETECTOR_FILE_FORMAT[] = { "dat", "datx" }; //!< JIO binary file format
59  static const char* const KM3NET_DETECTOR_FILE_FORMAT = "detx"; //!< %KM3NeT standard ASCII format
60  static const char* const ZIPPED_DETECTOR_FILE_FORMAT = "gz"; //!< zipped %KM3NeT standard ASCII format
61  static const char* const GDML_DETECTOR_FILE_FORMAT = "gdml"; //!< KM3Sim input format
62 
63  static const char* const GDML_SCHEMA = getenv("GDML_SCHEMA_DIR"); //!< directory necessary for correct GDML header output
64  static const char* const CAN_MARGIN_M = getenv("CAN_MARGIN_M"); //!< extension of the detector size to comply with the can definition
65  static const char* const G4GDML_DEFAULT_SCHEMALOCATION = "http://service-spi.web.cern.ch/service-spi/app/releases/GDML/schema/gdml.xsd";
66 
67 
68  /**
69  * Get maximal distance between modules in detector.
70  *
71  * \param detector detector
72  * \return maximal distance [m]
73  */
74  inline double getMaximalDistance(const JDetector& detector)
75  {
76  using namespace JPP;
77 
78  double dmax = 0.0;
79 
80  for (JDetector::const_iterator i = detector.begin(); i != detector.end(); ++i) {
81  for (JDetector::const_iterator j = detector.begin(); j != i; ++j) {
82  if (getDistance(i->getPosition(), j->getPosition()) > dmax) {
83  dmax = getDistance(i->getPosition(), j->getPosition());
84  }
85  }
86  }
87 
88  return dmax;
89  }
90 
91 
92  /**
93  * Get rotation over X axis in Geant4 coordinate system
94  *
95  * \param dir direction
96  * \return X-rotation [deg]
97  */
98  inline double GetXrotationG4(const JVersor3D dir)
99  {
100  using namespace JPP;
101 
102  const double phi = atan2(dir.getDY(), dir.getDZ())*(180.0/PI);
103 
104  if (phi < 0.0){
105  return phi + 360.0;
106  }
107  else{
108  return phi;
109  }
110  }
111 
112 
113  /**
114  * Get rotation over Y axis in Geant4 coordinate system
115  *
116  * \param dir direction
117  * \return Y-rotation [deg]
118  */
119  inline double GetYrotationG4(const JVersor3D dir)
120  {
121  using namespace JPP;
122 
123  return asin(-dir.getDX())*(180.0/PI);
124  }
125 
126 
127  inline void read_gdml(std::istream&, JDetector&)
128  {}
129 
130 
131  /**
132  * Writes KM3Sim GDML input file from detector
133  *
134  * \param out output stream
135  * \param detector detector
136  */
137  inline void write_gdml(std::ostream& out, const JDetector& detector)
138  {
139  using namespace std;
140  using namespace JPP;
141 
142  const double DEFAULT_CAN_MARGIN_M = 350.0; // default can margin [m]
143  const double DEFAULT_WORLD_MARGIN_M = 50.0; // default world margin [m]
144 
145  const JCylinder3D cylinder(detector.begin(), detector.end());
146 
147  double can_margin;
148 
149  if (CAN_MARGIN_M) {
150  can_margin = atof(CAN_MARGIN_M);
151  } else {
152  cerr << "CAN_MARGIN_M not defined! Setting standard CAN_MARGIN_M " << DEFAULT_CAN_MARGIN_M << " m." << endl;
153  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)
154  }
155 
156  const double WorldCylinderHeight = 2*(cylinder.getZmax() - cylinder.getZmin() + can_margin + DEFAULT_WORLD_MARGIN_M);
157  const double WorldRadius = cylinder.getLength() + cylinder.getRadius() + can_margin + DEFAULT_WORLD_MARGIN_M;
158 
159  const double Crust_Z_size = WorldCylinderHeight/2;
160  const double Crust_Z_position = -WorldCylinderHeight/4;
161 
162  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=\"";
163  if (!GDML_SCHEMA) {
164  cerr << "GDML_SCHEMA_DIR NOT DEFINED! Setting default path." << endl;
165  out << G4GDML_DEFAULT_SCHEMALOCATION << "\">\n\n\n";
166  } else {
167  out << GDML_SCHEMA << "gdml.xsd\">\n\n\n";
168  }
169  out << "<!-- Jpp version: "<< getGITVersion() << " -->\n";
170  out << "<define>\n";
171  out << "<rotation name=\"identity\"/>\n<position name=\"zero\"/>\n";
172 
173  int PMTs_NO = 0;
174 
175  for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
176 
177  if (module->getFloor() != 0) {
178 
179  const JVector3D center = module->getCenter();
180 
181  out << "<position name=\"PosString" << module->getString() << "_Dom" << module->getID() << "\" unit=\"m\" x=\"" << module->getX() << "\" y=\"" << module->getY() << "\" z=\"" << module->getZ() << "\"/>\n";
182 
183  for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
184 
185  const JVector3D vec = static_cast<JVector3D>(*pmt).sub(center);
186  out << "<position name=\"CathodPosition" << pmt->getID() << "_" << module->getID() << "\" unit=\"m\" x=\"" << vec.getX() << "\" y=\"" << vec.getY() << "\" z=\"" << vec.getZ() << "\"/>\n";
187  out << "<rotation name=\"CathodRotation" << pmt->getID() << "_" << module->getID() << "\" unit=\"deg\" x=\"" << GetXrotationG4(*pmt) << "\" y=\"" << GetYrotationG4(*pmt) << "\" z=\"0.000000\"/>\n";
188  out << "<constant name=\"CathodID_" << PMTs_NO << "\" value=\"" << pmt->getID() << "\"/>\n";
189  PMTs_NO++;
190  }
191  }
192  }
193 
194  out << "<position name=\"OMShift\" unit=\"m\" x=\"0\" y=\"0\" z=\"0.0392\"/>\n";
195  out << "\n\n\n";
196  out << "<!-- end of DU position definitions -->\n<position name=\"CrustPosition\" unit=\"m\" x=\"0\" y=\"0\" z=\"" << Crust_Z_position << "\"/>\n";
197 
198  out << "</define>\n";
199  out << "<materials>\n";
200  out << "</materials>\n";
201  out << "<solids>\n";
202  out << " <box name=\"CrustBox\" lunit=\"m\" x=\"2200\" y=\"2200\" z=\"" << Crust_Z_size << "\"/>\n";
203  out << " <box name=\"StoreyBox\" lunit=\"m\" x=\"0.6\" y=\"0.6\" z=\"0.6\"/>\n";
204  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";
205  out << " <tube name=\"CathodTube\" lunit=\"cm\" aunit=\"deg\" rmin=\"0.0\" rmax=\"4.7462\" z=\"0.5\" startphi=\"0.0\" deltaphi=\"360.0\"/>\n";
206  out << " <tube name=\"WorldTube\" lunit=\"m\" aunit=\"deg\" rmin=\"0.0\" rmax=\"" << WorldRadius << "\" z=\"" << WorldCylinderHeight << "\" startphi=\"0.0\" deltaphi=\"360.0\"/>\n";
207  out << "</solids>\n\n\n";
208 
209  out << "<structure>\n";
210  out << " <volume name=\"CathodVolume\">\n";
211  out << " <materialref ref=\"Cathod\"/>\n";
212  out << " <solidref ref=\"CathodTube\"/>\n";
213  out << " </volume>\n";
214 
215  out << "<!-- OMVolume(s) construction -->\n";
216 
217  for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
218 
219  out << " <volume name=\"OMVolume" << module->getID() << "\">\n";
220  out << " <materialref ref=\"Water\"/>\n";
221  out << " <solidref ref=\"OMSphere\"/>\n";
222 
223  for (JModule::const_iterator pmt = module->begin(); pmt != module->end(); ++pmt) {
224  out << " <physvol>\n";
225  out << " <volumeref ref=\"CathodVolume\"/>\n";
226  out << " <positionref ref=\"CathodPosition" << pmt->getID() << "_" << module->getID() << "\"/>\n";
227  out << " <rotationref ref=\"CathodRotation" << pmt->getID() << "_" << module->getID() << "\"/>\n";
228  out << " </physvol>\n";
229  }
230 
231  out << " </volume>\n";
232  }
233 
234  out << "<!-- StoreyVolume(s) construction -->\n";
235 
236  for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
237  out << " <volume name=\"StoreyVolume" << module->getID() << "\">\n";
238  out << " <materialref ref=\"Water\"/>\n";
239  out << " <solidref ref=\"StoreyBox\"/>\n";
240  out << " <physvol>\n";
241  out << " <volumeref ref=\"OMVolume" << module->getID() << "\"/>\n";
242  out << " <positionref ref=\"OMShift\"/>\n";
243  out << " <rotationref ref=\"identity\"/>\n";
244  out << " </physvol>\n";
245  out << " </volume>\n";
246  }
247 
248  out << "<!-- Crust Volume construction-->\n";
249  out << "<volume name=\"CrustVolume\">\n";
250  out << " <materialref ref=\"Crust\"/>\n";
251  out << " <solidref ref=\"CrustBox\"/>\n";
252  out << "</volume>\n";
253 
254  out << "<!-- World Volume construction-->\n";
255  out << "<volume name=\"WorldVolume\">\n";
256  out << " <materialref ref=\"Water\"/>\n";
257  out << " <solidref ref=\"WorldTube\"/>\n";
258 
259  out << " <physvol>\n";
260  out << " <volumeref ref=\"CrustVolume\"/>\n";
261  out << " <positionref ref=\"CrustPosition\"/>\n";
262  out << " <rotationref ref=\"identity\"/>\n";
263  out << " </physvol>\n";
264 
265  for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
266  out << " <physvol>\n";
267  out << " <volumeref ref=\"StoreyVolume" << module->getID() << "\"/>\n";
268  out << " <positionref ref=\"PosString" << module->getString() << "_Dom" << module->getID() << "\"/>\n";
269  out << " <rotationref ref=\"identity\"/>\n";
270  out << " </physvol>\n";
271  }
272 
273  out << "</volume>\n";
274 
275  out << "</structure>\n";
276  out << "<setup name=\"Default\" version=\"1.0\">\n";
277  out << "<world ref=\"WorldVolume\"/>\n";
278  out << "</setup>\n";
279  out << "</gdml>\n";
280  }
281 
282 
283  /**
284  * Get maximal time between modules in detector following causality.
285  *
286  * \param detector detector
287  * \return maximal time [ns]
288  */
289  inline double getMaximalTime(const JDetector& detector)
290  {
291  using namespace JPP;
292 
294  }
295 
296 
297  /**
298  * Get maximal time between modules in detector following causality.
299  * The road width corresponds to the maximal distance traveled by the light.
300  *
301  * \param detector detector
302  * \param roadWidth_m road width [m]
303  * \return maximal time [ns]
304  */
305  inline double getMaximalTime(const JDetector& detector, const double roadWidth_m)
306  {
307  using namespace JPP;
308 
309  const double Dmax_m = getMaximalDistance(detector);
310 
311  return (sqrt((Dmax_m + roadWidth_m*getSinThetaC()) *
312  (Dmax_m - roadWidth_m*getSinThetaC())) +
313  roadWidth_m * getSinThetaC() * getTanThetaC()) * getInverseSpeedOfLight();
314  }
315 
316 
317  /**
318  * Get de-calibrated time range.
319  *
320  * The de-calibrated time range is corrected for minimal and maximal time offset of PMTs in given module.
321  *
322  * \param timeRange time range [ns]
323  * \param module module
324  * \return time range [ns]
325  */
326  inline JTimeRange getTimeRange(const JTimeRange& timeRange, const JModule& module)
327  {
328  if (!module.empty()) {
329 
331 
332  for (JModule::const_iterator pmt = module.begin(); pmt != module.end(); ++pmt) {
333 
334  const JCalibration& calibration = pmt->getCalibration();
335 
336  time_range.include(putTime(timeRange.getLowerLimit(), calibration));
337  time_range.include(putTime(timeRange.getUpperLimit(), calibration));
338  }
339 
340  return time_range;
341 
342  } else {
343 
344  return timeRange;
345  }
346  }
347 
348 
349  /**
350  * Get number of PMTs.
351  *
352  * \param module module
353  * \return number of PMTs
354  */
355  inline int getNumberOfPMTs(const JModule& module)
356  {
357  return module.size();
358  }
359 
360 
361  /**
362  * Get number of PMTs.
363  *
364  * \param detector detector
365  * \return number of PMTs
366  */
367  inline int getNumberOfPMTs(const JDetector& detector)
368  {
369  int number_of_pmts = 0;
370 
371  for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
372  number_of_pmts += getNumberOfPMTs(*module);
373  }
374 
375  return number_of_pmts;
376  }
377 
378 
379  /**
380  * Get list of strings IDs.
381  *
382  * \param detector detector
383  * \return list of string IDs
384  */
386  {
387  std::set<int> buffer;
388 
389  for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
390  buffer.insert(module->getString());
391  }
392 
393  return buffer;
394  }
395 
396 
397  /**
398  * Get number of floors.
399  *
400  * \param detector detector
401  * \return number of floors
402  */
404  {
405  std::set<int> buffer;
406 
407  for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
408  buffer.insert(module->getFloor());
409  }
410 
411  return buffer.size();
412  }
413 
414 
415  /**
416  * Get number of modules.
417  *
418  * \param detector detector
419  * \return number of modules
420  */
422  {
423  std::set<int> buffer;
424 
425  for (JDetector::const_iterator module = detector.begin(); module != detector.end(); ++module) {
426  buffer.insert(module->getID());
427  }
428 
429  return buffer.size();
430  }
431 
432 
433  /**
434  * Load detector from input file.
435  *
436  * Supported file formats:
437  * - ASCII file, extension JDETECTOR::GENDET_DETECTOR_FILE_FORMAT, gendet format;
438  * - binary file, extension JDETECTOR::BINARY_DETECTOR_FILE_FORMAT, Jpp internal format;
439  * - ASCII file, extension JDETECTOR::KM3NET_DETECTOR_FILE_FORMAT, %KM3NeT standard format;
440  * - gzipped file, extension JDETECTOR::ZIPPED_DETECTOR_FILE_FORMAT, %KM3NeT standard format;
441  *
442  * \param file_name file name
443  * \param detector detector
444  */
445  inline void load(const std::string& file_name, JDetector& detector)
446  {
447  using namespace std;
448  using namespace JPP;
449 
451 
452  JMonteCarloDetector buffer(true);
453 
454  ifstream in(file_name.c_str());
455 
456  if (!in) {
457  THROW(JFileOpenException, "File not opened: " << file_name);
458  }
459 
460  in >> buffer;
461 
462  in.close();
463 
464  detector.swap(buffer);
465 
466  } else if (getFilenameExtension(file_name) == BINARY_DETECTOR_FILE_FORMAT[0] ||
468 
469  JFileStreamReader in(file_name.c_str());
470 
471  if (!in) {
472  THROW(JFileOpenException, "File not opened: " << file_name);
473  }
474 
475  detector.read(in);
476 
477  in.close();
478 
479  } else if (getFilenameExtension(file_name) == KM3NET_DETECTOR_FILE_FORMAT) {
480 
481  ifstream in(file_name.c_str());
482 
483  if (!in) {
484  THROW(JFileOpenException, "File not opened: " << file_name);
485  }
486 
487  in >> detector;
488 
489  in.close();
490 
491  } else if (getFilenameExtension(file_name) == ZIPPED_DETECTOR_FILE_FORMAT) {
492 
493  igzstream in(file_name.c_str());
494 
495  if (!in) {
496  THROW(JFileOpenException, "File not opened: " << file_name);
497  }
498 
499  in >> detector;
500 
501  in.close();
502 
503  } else {
504 
505  THROW(JProtocolException, "Protocol not defined: " << file_name);
506  }
507  }
508 
509 
510  /**
511  * Store detector to output file.
512  *
513  * Supported file formats:
514  * - binary file, extension JDETECTOR::BINARY_DETECTOR_FILE_FORMAT, Jpp internal format;
515  * - ASCII file, extension JDETECTOR::KM3NET_DETECTOR_FILE_FORMAT, %KM3NeT standard format;
516  * - gzipped file, extension JDETECTOR::ZIPPED_DETECTOR_FILE_FORMAT, %KM3NeT standard format;
517  * - gdml file, extension JDETECTOR::GDML_DETECTOR_FILE_FORMAT, KM3Sim input format;
518  *
519  * \param file_name file name
520  * \param detector detector
521  */
522  inline void store(const std::string& file_name, const JDetector& detector)
523  {
524  using namespace std;
525  using namespace JPP;
526 
527  if (getFilenameExtension(file_name) == BINARY_DETECTOR_FILE_FORMAT[1]) {
528 
529  JFileStreamWriter out(file_name.c_str());
530 
531  detector.write(out);
532 
533  out.close();
534 
535  } else if (getFilenameExtension(file_name) == KM3NET_DETECTOR_FILE_FORMAT) {
536 
537  std::ofstream out(file_name.c_str());
538 
539  out << detector;
540 
541  out.close();
542 
543  } else if (getFilenameExtension(file_name) == ZIPPED_DETECTOR_FILE_FORMAT) {
544 
545  ogzstream out(file_name.c_str());
546 
547  out << detector;
548 
549  out.close();
550 
551  } else if (getFilenameExtension(file_name) == GDML_DETECTOR_FILE_FORMAT) {
552 
553  std::ofstream out(file_name.c_str());
554 
555  write_gdml(out, detector);
556 
557  out.close();
558 
559  } else {
560 
561  THROW(JProtocolException, "Protocol not defined: " << file_name);
562  }
563  }
564 
565 
566  /**
567  * Get module according module address map.
568  *
569  * \param memo module address map
570  * \param id module identifier
571  * \param location module location
572  * \return module
573  */
574  inline const JModule& getModule(const JModuleAddressMap& memo,
575  const int id = -1,
576  const JLocation& location = JLocation())
577  {
578  static JModule module;
579 
580 
581  module.setID(id);
582 
583  module.setLocation(location);
584 
585  module.resize(memo.size());
586 
587  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))); }
588 
589  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))); }
590  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))); }
591  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))); }
592  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))); }
593  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))); }
594  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))); }
595 
596  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))); }
597  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))); }
598  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))); }
599  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))); }
600  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))); }
601  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))); }
602 
603  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))); }
604  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))); }
605  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))); }
606  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))); }
607  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))); }
608  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))); }
609 
610  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))); }
611  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))); }
612  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))); }
613  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))); }
614  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))); }
615  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))); }
616 
617  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))); }
618  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))); }
619  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))); }
620  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))); }
621  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))); }
622  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))); }
623 
624  module.compile();
625 
626  return module;
627  }
628 
629 
630  /**
631  * Get module corresponding to Antares storey.
632  *
633  * \param id module identifier
634  * \param location module location
635  * \return module
636  */
637  inline const JModule& getModule(const int id,
638  const JLocation& location = JLocation())
639  {
640  static JModule module;
641 
642  module.setID(id);
643 
644  module.setLocation(location);
645 
646  if (module.empty()) {
647 
648  module.resize(3);
649 
650  const double R = 0.5; // [m]
651 
652  const double st = sin(0.75*PI);
653  const double ct = cos(0.75*PI);
654 
655  for (int i = 0; i != 3; ++i) {
656 
657  const double phi = (2.0*PI*i) / 3.0;
658  const double cp = cos(phi);
659  const double sp = sin(phi);
660 
661  module[i] = JPMT(i, JAxis3D(JVector3D(R*st*cp, R*st*sp, R*ct), JVersor3D(st*cp, st*sp, ct)));
662  }
663  }
664 
665  return module;
666  }
667 
668 
669  /**
670  * Auxiliary class to get rotation matrix between two optical modules.
671  */
672  struct JRotation :
673  public JRotation3D
674  {
675 
676  static const size_t NUMBER_OF_DIMENSIONS = 3; //!< Number of dimensions
677 
678 
679  /**
680  * Get rotation matrix to go from first to second module.
681  *
682  * \param first first module
683  * \param second second module
684  * \return rotation matrix
685  */
686  const JRotation3D& operator()(const JModule& first, const JModule& second)
687  {
688  this->setIdentity();
689 
690  if (first.size() == second.size()) {
691 
692  const size_t N = first.size();
693 
694  if (N >= NUMBER_OF_DIMENSIONS) {
695 
696  in .resize(N);
697  out.resize(N);
698 
699  for (size_t i = 0; i != N; ++i) {
700  in [i] = first .getPMT(i).getDirection();
701  out[i] = second.getPMT(i).getDirection();
702  }
703 
704  for (size_t i = 0; i != NUMBER_OF_DIMENSIONS; ++i) {
705  if (!orthonormalise(i)) {
706  THROW(JException, "Failure to orthonormalise direction " << i);
707  }
708  }
709 
710  this->a00 = out[0].getX() * in[0].getX() + out[1].getX() * in[1].getX() + out[2].getX() * in[2].getX();
711  this->a01 = out[0].getX() * in[0].getY() + out[1].getX() * in[1].getY() + out[2].getX() * in[2].getY();
712  this->a02 = out[0].getX() * in[0].getZ() + out[1].getX() * in[1].getZ() + out[2].getX() * in[2].getZ();
713 
714  this->a10 = out[0].getY() * in[0].getX() + out[1].getY() * in[1].getX() + out[2].getY() * in[2].getX();
715  this->a11 = out[0].getY() * in[0].getY() + out[1].getY() * in[1].getY() + out[2].getY() * in[2].getY();
716  this->a12 = out[0].getY() * in[0].getZ() + out[1].getY() * in[1].getZ() + out[2].getY() * in[2].getZ();
717 
718  this->a20 = out[0].getZ() * in[0].getX() + out[1].getZ() * in[1].getX() + out[2].getZ() * in[2].getX();
719  this->a21 = out[0].getZ() * in[0].getY() + out[1].getZ() * in[1].getY() + out[2].getZ() * in[2].getY();
720  this->a22 = out[0].getZ() * in[0].getZ() + out[1].getZ() * in[1].getZ() + out[2].getZ() * in[2].getZ();
721 
722  } else {
723 
724  THROW(JException, "Module " << first.getID() << " size " << N << " < " << NUMBER_OF_DIMENSIONS);
725  }
726 
727  } else {
728 
729  THROW(JException, "Module " << first.getID() << " size " << first.size() << " != " << second.size());
730  }
731 
732  return *this;
733  }
734 
735  private:
736  /**
737  * Put normalised primary direction at specified index and orthoganilise following.\n
738  * This procedure follows Gram-Schmidt process.
739  *
740  * \param index index
741  * \param precision precision
742  * \return true if primary direction exists; else false
743  */
744  bool orthonormalise(const size_t index, const double precision = std::numeric_limits<double>::epsilon())
745  {
746  using namespace std;
747 
748  size_t pos = index;
749 
750  for (size_t i = index + 1; i != in.size(); ++i) {
751  if (in[i].getLengthSquared() > in[pos].getLengthSquared()) {
752  pos = i;
753  }
754  }
755 
756  const double u = in[pos].getLength();
757 
758  if (u > precision) {
759 
760  in [pos] /= u;
761  out[pos] /= u;
762 
763  if (pos != index) {
764  swap(in [pos], in [index]);
765  swap(out[pos], out[index]);
766  }
767 
768  for (size_t i = index + 1; i != in.size(); ++i) {
769 
770  const double dot = in[index].getDot(in[i]);
771 
772  in [i] -= dot * in [index];
773  out[i] -= dot * out[index];
774  }
775 
776  return true;
777 
778  } else {
779 
780  return false;
781  }
782  }
783 
784 
787  };
788 
789 
790  /**
791  * Function object to get rotation matrix to go from first to second module.
792  */
794 
795 
796  /**
797  * Get position to go from first to second module.
798  *
799  * \param first first module
800  * \param second second module
801  * \return position
802  */
803  inline JPosition3D getPosition(const JModule& first, const JModule& second)
804  {
805  return second.getPosition() - first.getPosition();
806  }
807 
808 
809  /**
810  * Get calibration to go from first to second calibration.
811  *
812  * \param first first calibration
813  * \param second second calibration
814  * \return calibration
815  */
817  {
818  return JCalibration(second.getT0() - first.getT0());
819  }
820 }
821 
822 #endif
Exception for opening of file.
Definition: JException.hh:342
static const JRange< double, std::less< double > > DEFAULT_RANGE
Default range.
Definition: JRange.hh:568
double GetYrotationG4(const JVersor3D dir)
Get rotation over Y axis in Geant4 coordinate system.
General exception.
Definition: JException.hh:23
Exceptions.
Auxiliary methods for geometrical methods.
Data structure for a composite optical module.
Definition: JModule.hh:57
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:80
const JDirection3D & getDirection() const
Get direction.
JTOOLS::JRange< double > JTimeRange
Type definition for time range (unit [ns]).
Rotation matrix.
Definition: JRotation3D.hh:111
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Definition: JException.hh:670
std::set< int > getStringIDs(const JDetector &detector)
Get list of strings IDs.
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.
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.
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
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
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
double getMaximalDistance(const JDetector &detector)
Get maximal distance between modules in detector.
Cylinder object.
Definition: JCylinder3D.hh:39
virtual JReader & read(JReader &in) override
Read from input.
Definition: JDetector.hh:390
Detector file.
Definition: JHead.hh:196
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:441
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 and calibration.
Definition: JPMT.hh:47
void compile()
Compile module data.
Definition: JModule.hh:313
void store(const std::string &file_name, const JDetector &detector)
Store detector to output file.
JPosition3D getPosition(const Vec &pos)
Get position.
int getNumberOfFloors(const JDetector &detector)
Get number of floors.
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:211
Logical location of module.
Protocol exception.
Definition: JException.hh:630
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 echo Variable JPP_DIR undefined exit fi source $JPP_DIR setenv sh $JPP_DIR set_variable NORTH set_variable EAST set_variable SOUTH set_variable WEST set_variable WORKDIR tmp set_variable R set_variable CT set_variable YMAX set_variable YMIN if do_usage *then usage $script[distance] fi case set_variable R
Definition: JDrawLED.sh:35
static const char *const GENDET_DETECTOR_FILE_FORMAT
File name extensions.
void load(const std::string &file_name, JDetector &detector)
Load detector from input file.
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:69
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
static const char *const G4GDML_DEFAULT_SCHEMALOCATION
then cp
double getTanThetaC()
Get average tangent of Cherenkov angle of water corresponding to group velocity.
int j
Definition: JPolint.hh:666
Data structure for position in three dimensions.
Definition: JPosition3D.hh:36
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:739
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 source JAcoustics sh $DETECTOR_ID CHECK_EXIT_CODE typeset A TRIPODS get_tripods $WORKDIR tripod txt TRIPODS for EMITTER in
Definition: JCanberra.sh:38
Binary buffered file output.
then usage $script[input file[working directory[option]]] nWhere option can be N
Definition: JMuonPostfit.sh:35
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
Binary buffered file input.
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
bool orthonormalise(const size_t index, const double precision=std::numeric_limits< double >::epsilon())
Put normalised primary direction at specified index and orthoganilise following.
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.