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