KaliVeda
Toolkit for HIC analysis
INDRAGeometryBuilder.cpp
1 //Created by KVClassFactory on Wed Feb 1 11:09:41 2012
2 //Author: John Frankland,,,
3 
4 #include "INDRAGeometryBuilder.h"
5 #include "TEnv.h"
6 #include "TMath.h"
7 #include "TString.h"
8 #include "TGeoMedium.h"
9 #include "TRotation.h"
10 #include "TGeoMatrix.h"
11 #include "TGeoManager.h"
12 #include "TGeoCompositeShape.h"
13 #include "TGeoEltu.h"
14 
15 #include "KVINDRA.h"
16 #include "KVDataSet.h"
17 
18 using namespace std;
19 
21 
22 
23 
28 void INDRAGeometryBuilder:: CorrectCoordinates(Double_t* coo, Double_t& offX, Double_t& offY)
29 {
30  // calculate offset in X and Y
31  // correct coordinates for offset
32  // return offset TGeoTranslation
33 
34  offX = offY = 0;
35  for (int i = 0; i < 8; i++) {
36  offX += coo[2 * i];
37  offY += coo[2 * i + 1];
38  }
39  offX /= 8.;
40  offY /= 8.;
41  for (int i = 0; i < 8; i++) {
42  coo[2 * i] -= offX;
43  coo[2 * i + 1] -= offY;
44  }
45 }
46 
47 
48 
51 
53 {
54  // Default constructor
55  fEtalonVol = 0;
56 }
57 
58 
59 
60 
67 
69 {
70  // Copy constructor
71  // This ctor is used to make a copy of an existing object (for example
72  // when a method returns an object), and it is always a good idea to
73  // implement it.
74  // If your class allocates memory in its constructor(s) then it is ESSENTIAL :-)
75 
76  fEtalonVol = 0;
77  obj.Copy(*this);
78 }
79 
80 
81 
84 
86 {
87  // Destructor
88 }
89 
90 
91 
92 
100 
102 {
103  // This method copies the current state of 'this' object into 'obj'
104  // You should add here any member variables, for example:
105  // (supposing a member variable INDRAGeometryBuilder::fToto)
106  // CastedObj.fToto = fToto;
107  // or
108  // CastedObj.SetToto( GetToto() );
109 
110  TObject::Copy(obj);
111  //INDRAGeometryBuilder& CastedObj = (INDRAGeometryBuilder&)obj;
112 }
113 
114 
115 
122 
124 {
125  // Given an array of ncoords points frontcoords[ncoords] which lie in a plane
126  // calculate the corresponding points on a parallel plane which is
127  // at a distance from the origin which is greater by depth
128  // (distance plane-origin = length of normal to plane passing through origin)
129  // 'normal' is vector point of intersection plane-normal to origin
130 
131  Double_t planeDist = normal.Mag();//distance original plane-origin
132  for (int i = 0; i < 4; i++) {
133  Double_t rap = (planeDist + depth) / planeDist;
134  backcoords[i] = rap * frontcoords[i];
135  }
136 }
137 
138 
139 
143 
145 {
146  // Read infos in CAO file for this detector.
147  // We look for a TEnv file with name "detname.cao"
148 
149  TEnv infos;
150  TString path = Form("%s.cao", detname);
151  SearchKVFile(path.Data(), path, "data");
152  infos.ReadFile(path, kEnvAll);
153 
154  Double_t unit_converter = 0.1;// distances in file given in mm: convert to cm
155 
156  fInnerFront[0].SetX(infos.GetValue("INNER.A.X", 0.0)*unit_converter);
157  fInnerFront[0].SetY(infos.GetValue("INNER.A.Y", 0.0)*unit_converter);
158  fInnerFront[0].SetZ(infos.GetValue("INNER.A.Z", 0.0)*unit_converter);
159  fInnerFront[3].SetX(infos.GetValue("INNER.B.X", 0.0)*unit_converter);
160  fInnerFront[3].SetY(infos.GetValue("INNER.B.Y", 0.0)*unit_converter);
161  fInnerFront[3].SetZ(infos.GetValue("INNER.B.Z", 0.0)*unit_converter);
162  fInnerFront[2].SetX(infos.GetValue("INNER.C.X", 0.0)*unit_converter);
163  fInnerFront[2].SetY(infos.GetValue("INNER.C.Y", 0.0)*unit_converter);
164  fInnerFront[2].SetZ(infos.GetValue("INNER.C.Z", 0.0)*unit_converter);
165  fInnerFront[1].SetX(infos.GetValue("INNER.D.X", 0.0)*unit_converter);
166  fInnerFront[1].SetY(infos.GetValue("INNER.D.Y", 0.0)*unit_converter);
167  fInnerFront[1].SetZ(infos.GetValue("INNER.D.Z", 0.0)*unit_converter);
168 
169  // To get back to INDRA phi-coordinates, all points need to be rotated
170  // by -150 degrees around the Z-axis
171  for (int i = 0; i <= 3; i++) {
172  fInnerFront[i].RotateZ(-150.*TMath::DegToRad());
173  }
175 
176  fOuterFront[0].SetX(infos.GetValue("OUTER.A.X", 0.0)*unit_converter);
177  fOuterFront[0].SetY(infos.GetValue("OUTER.A.Y", 0.0)*unit_converter);
178  fOuterFront[0].SetZ(infos.GetValue("OUTER.A.Z", 0.0)*unit_converter);
179  fOuterFront[3].SetX(infos.GetValue("OUTER.B.X", 0.0)*unit_converter);
180  fOuterFront[3].SetY(infos.GetValue("OUTER.B.Y", 0.0)*unit_converter);
181  fOuterFront[3].SetZ(infos.GetValue("OUTER.B.Z", 0.0)*unit_converter);
182  fOuterFront[2].SetX(infos.GetValue("OUTER.C.X", 0.0)*unit_converter);
183  fOuterFront[2].SetY(infos.GetValue("OUTER.C.Y", 0.0)*unit_converter);
184  fOuterFront[2].SetZ(infos.GetValue("OUTER.C.Z", 0.0)*unit_converter);
185  fOuterFront[1].SetX(infos.GetValue("OUTER.D.X", 0.0)*unit_converter);
186  fOuterFront[1].SetY(infos.GetValue("OUTER.D.Y", 0.0)*unit_converter);
187  fOuterFront[1].SetZ(infos.GetValue("OUTER.D.Z", 0.0)*unit_converter);
188 
189  // To get back to INDRA phi-coordinates, all points need to be rotated
190  // by -150 degrees around the Z-axis
191  for (int i = 0; i <= 3; i++) {
192  fOuterFront[i].RotateZ(-150.*TMath::DegToRad());
193  }
195 
196  phi0 = infos.GetValue("PHIZERO", 30.0);
197  thetaMin = infos.GetValue("THETAMIN", 0.0);
198  thetaMax = infos.GetValue("THETAMAX", 0.0);
199  Ndets = infos.GetValue("NDETS", 1);
200  deltaPhi = 360. / Ndets;
201 
202  // calculate theoretical geometry:
203  // points of intersection with the plane defined by real Huguet geometry
204  // and the 4 vectors to theoretical thetamin/max phimin/max
207  Ph0 - deltaPhi / 2.,
208  Ph0 + deltaPhi / 2.,
209  fFrameFront);
210  // calculate centre of frame = direction of detector
212  fFrameMat.SetMaterial(infos.GetValue("FRAME.MATERIAL", "Al"));
213 
214  fInnerPads = infos.GetValue("INNER.PADS", 1);
215  fOuterPads = infos.GetValue("OUTER.PADS", 0);
216  fInnerRing = infos.GetValue("INNER.RING", ring);
217  fOuterRing = infos.GetValue("OUTER.RING", 0);
218  fInnerDmod = infos.GetValue("INNER.DMOD", 1);
219  fOuterDmod = infos.GetValue("OUTER.DMOD", 1);
220  fInnerModmin = infos.GetValue("INNER.MODMIN", 1);
221  fOuterModmin = infos.GetValue("OUTER.MODMIN", 1);
222  fModmax = infos.GetValue("MODMAX", 24);
223 }
224 
225 
226 
227 
229 
231 {
232  printf("Detector name : %s\n", fDetName.Data());
233  printf("Total thickness : %f cm\n", fTotalThickness);
234  printf("Frame centre:\n");
236  printf("Inner centre:\n");
238  printf("Outer centre: \n");
240  printf("Coordinates of outer pads :\n");
241  for (int i = 0; i < 4; i++) fOuterFront[i].Print();
242  printf("Coordinates of inner pads :\n");
243  for (int i = 0; i < 4; i++) fInnerFront[i].Print();
244  printf("Material of outer frame : %s\n", fFrameMat.GetTitle());
245 }
246 
247 
248 
249 
253 
255 {
256  // Create the TGeoVolume corresponding to the outer casing
257  // (dead zone) of the detector
258 
259  TVector3 fFrameBack[4];
260  TVector3 fFrameBackCentre;
261  //CalculateBackPlaneCoordinates(fFrameFront, fFrameCentre, fTotalThickness, fFrameBack);
262  // make deadzone be 1um thick
263  Double_t dz = 5.e-5;
265  CalculateCentre(fFrameBack, fFrameBackCentre);
266 
267  TVector3 corners[8]; // 8 vertices of the volume
269  TransformToOwnFrame(fFrameBack, fFrameBackCentre, &corners[4]);
270 
271  Double_t vertices[16];
272  for (int i = 0; i < 8; i++) {
273  vertices[2 * i] = corners[i].X();
274  vertices[2 * i + 1] = corners[i].Y();
275  }
276 
277  //Double_t dz = 0.99 * fTotalThickness / 2.;
278  TString vol_name;
279  vol_name.Form("STRUCT_%s_%02d", det_type.Data(), ring_num);
282  vol_name.Form("DEADZONE_%s_%02d", det_type.Data(), ring_num);
284  Double_t offX, offY;
285  CorrectCoordinates(vertices, offX, offY);
286  // place the deadzone 1um (=1.e-4 cm) behind the detector entrance window
287  TGeoTranslation* offset = new TGeoTranslation(offX, offY, -(0.5 * fTotalThickness - (1.e-4 + dz)));
288  TGeoVolume* frame = gGeoManager->MakeArb8(vol_name.Data(), med, dz, vertices);
289  frame->SetLineColor(med->GetMaterial()->GetDefaultColor());
290  fFrameVolume->AddNode(frame, 1, offset);
291 }
292 
293 
294 
295 
299 
301 {
302  // takes the four points (TVector3) in the array and transforms them
303  // to a reference frame in which the +ve z-axis goes through their centre
304 
305  TRotation rot_to_frame;
306  rot_to_frame.SetYEulerAngles(-centre.Phi(), -centre.Theta(), 0.);
307  TVector3 displZ(0, 0, centre.Mag());
308  for (int i = 0; i < 4; i++) {
309  ownframe[i] = rot_to_frame * orig[i] - displZ;
310  }
311 }
312 
313 
314 
315 
316 
319 
321 {
322  // position frame (dead zone) volume in geometry
323 
325  TGeoRotation rot1, rot2;
326  rot2.SetAngles(phi + 90., theta, 0.);
327  rot1.SetAngles(-90., 0., 0.);
328  // distance to frame centre
329  Double_t trans_z = fFrameCentre.Mag() + fTotalThickness / 2.;
330 
331  TGeoTranslation tran(0, 0, trans_z);
332  TGeoHMatrix h = rot2 * tran * rot1;
333  TGeoHMatrix* ph = new TGeoHMatrix(h);
334 
335  // add detector volume to geometry
336  gGeoManager->GetTopVolume()->AddNode(fFrameVolume, copy_no, ph);
337 }
338 
339 
340 
341 
344 
346 {
347  // position detector inside frame
348 
351 }
352 
353 
354 
356 
358 {
359  KVDetector* thisdetector = gIndra->GetDetector(detname);
360  if (!thisdetector || !thisdetector->IsPresent()) {
361  //Info("CheckDetectorPresent", "%s is absent", detname.Data());
362  return kFALSE;
363  }
364  if (!fLayers) {
365  // get info on detector structure from first detector which is present on ring
366  fProtoDetector = thisdetector;
367  fLayers = thisdetector->GetListOfAbsorbers();
368  fActiveLayer = 1 + thisdetector->GetListOfAbsorbers()->IndexOf(thisdetector->GetActiveLayer());
369  fTotalThickness = thisdetector->GetTotalThicknessInCM();
370  }
371  if ((thisdetector != fProtoDetector) && !thisdetector->HasSameStructureAs(fProtoDetector)) {
372  // current detector does not have same structure as prototype
373  fProtoDetector = thisdetector;
374  fLayers = thisdetector->GetListOfAbsorbers();
375  fActiveLayer = 1 + thisdetector->GetListOfAbsorbers()->IndexOf(thisdetector->GetActiveLayer());
376  fTotalThickness = thisdetector->GetTotalThicknessInCM();
377  }
378  return kTRUE;
379 }
380 
381 
382 //void INDRAGeometryBuilder::MakeRing(TGeoVolume* MOTHER, const Char_t* det, int ring)
383 
385 
386 void INDRAGeometryBuilder::MakeRing(const Char_t* det, int ring)
387 {
388 
389  if (!strcmp(det, "PHOS"))
390  fDetName.Form("%s_01", det);
391  else
392  fDetName.Form("%s_%02d01", det, ring);
393  ReadDetCAO(fDetName, ring);
394  //Print();
395  Double_t phi = phi0;
396  Int_t innerMod = fInnerModmin;
397  Int_t outerMod = fOuterModmin;
398  int i = 1;
399 
400  cout << fDetName.Data() << " " << fInnerCentre.Mag() << " " <<
401  0.5 * (fInnerFront[0].Theta() + fInnerFront[3].Theta())*TMath::RadToDeg() << " " <<
402  0.5 * (fInnerFront[1].Theta() + fInnerFront[2].Theta())*TMath::RadToDeg() << " " <<
403  0.5 * (fInnerFront[2].Phi() + fInnerFront[3].Phi())*TMath::RadToDeg() << " " <<
404  0.5 * (fInnerFront[0].Phi() + fInnerFront[1].Phi())*TMath::RadToDeg() << endl;
405 
406 // check presence of all detectors of ring
407  Int_t npresent = 0;
408  Int_t ntotal = 0;
409  fLayers = nullptr;//will force CheckDetectorPresent() to get infos from first detector present
410  fProtoDetector = nullptr;
411  for (i = 1; i <= Ndets; i++) {
412  if (!strcmp(det, "PHOS")) fDetName.Form("%s_%02d", det, innerMod);
413  else fDetName.Form("%s_%02d%02d", det, fInnerRing, innerMod);
414  ntotal++;
415  npresent += (Int_t)CheckDetectorPresent(fDetName);
416 
417  innerMod += fInnerDmod;
418 
419  if (fInnerPads == 3) {
420  if (!strcmp(det, "PHOS")) fDetName.Form("%s_%02d", det, innerMod);
421  else fDetName.Form("%s_%02d%02d", det, fInnerRing, innerMod);
422  ntotal++;
423  npresent += (Int_t)CheckDetectorPresent(fDetName);
424  innerMod += fInnerDmod;
425  if (!strcmp(det, "PHOS")) fDetName.Form("%s_%02d", det, innerMod);
426  else fDetName.Form("%s_%02d%02d", det, fInnerRing, innerMod);
427  ntotal++;
428  npresent += (Int_t)CheckDetectorPresent(fDetName);
429  innerMod += fInnerDmod;
430  }
431  else {
432  if (fInnerPads == 2) {
433  if (!strcmp(det, "PHOS")) fDetName.Form("%s_%02d", det, innerMod);
434  else fDetName.Form("%s_%02d%02d", det, fInnerRing, innerMod);
435  ntotal++;
436  npresent += (Int_t)CheckDetectorPresent(fDetName);
437  innerMod += fInnerDmod;
438  }
439  if (fOuterPads) {
440  if (!strcmp(det, "PHOS")) fDetName.Form("%s_%02d", det, outerMod);
441  else fDetName.Form("%s_%02d%02d", det, fOuterRing, outerMod);
442  ntotal++;
443  npresent += (Int_t)CheckDetectorPresent(fDetName);
444  outerMod += fOuterDmod;
445  if (fOuterPads == 2) {
446  if (!strcmp(det, "PHOS")) fDetName.Form("%s_%02d", det, outerMod);
447  else fDetName.Form("%s_%02d%02d", det, fOuterRing, outerMod);
448  ntotal++;
449  npresent += (Int_t)CheckDetectorPresent(fDetName);
450  outerMod += fOuterDmod;
451  }
452  }
453  }
454  }
455  if (!npresent) {
456  Info("MakeRing", "Detector type %s ring number %d : ABSENT", det, ring);
457  return;
458  }
459  Info("MakeRing", "Detector type %s ring number %d : %d/%d detectors present", det, ring, npresent, ntotal);
460 
461  i = 1;
462 
463  innerMod = fInnerModmin;
464  outerMod = fOuterModmin;
465 
466  fLayers = nullptr;//will force CheckDetectorPresent() to get infos from first detector present
467  fProtoDetector = nullptr;
468  for (i = 1; i <= Ndets; i++) {
469 
470  // check if prototype information changes
471  KVDetector* oldProtoDet = fProtoDetector;
472 
473  // check absence of whole block
474  ntotal = 0;
475  npresent = 0;
476  if (!strcmp(det, "PHOS")) fDetName.Form("%s_%02d", det, innerMod);
477  else fDetName.Form("%s_%02d%02d", det, fInnerRing, innerMod);
478  ntotal++;
479  npresent += (Int_t)CheckDetectorPresent(fDetName);
480 
481  innerMod += fInnerDmod;
482 
483  if (fInnerPads == 3) {
484  if (!strcmp(det, "PHOS")) fDetName.Form("%s_%02d", det, innerMod);
485  else fDetName.Form("%s_%02d%02d", det, fInnerRing, innerMod);
486  ntotal++;
487  npresent += (Int_t)CheckDetectorPresent(fDetName);
488  innerMod += fInnerDmod;
489  if (!strcmp(det, "PHOS")) fDetName.Form("%s_%02d", det, innerMod);
490  else fDetName.Form("%s_%02d%02d", det, fInnerRing, innerMod);
491  ntotal++;
492  npresent += (Int_t)CheckDetectorPresent(fDetName);
493  innerMod += fInnerDmod;
494  }
495  else {
496  if (fInnerPads == 2) {
497  if (!strcmp(det, "PHOS")) fDetName.Form("%s_%02d", det, innerMod);
498  else fDetName.Form("%s_%02d%02d", det, fInnerRing, innerMod);
499  ntotal++;
500  npresent += (Int_t)CheckDetectorPresent(fDetName);
501  innerMod += fInnerDmod;
502  }
503  if (fOuterPads) {
504  if (!strcmp(det, "PHOS")) fDetName.Form("%s_%02d", det, outerMod);
505  else fDetName.Form("%s_%02d%02d", det, fOuterRing, outerMod);
506  ntotal++;
507  npresent += (Int_t)CheckDetectorPresent(fDetName);
508  outerMod += fOuterDmod;
509  if (fOuterPads == 2) {
510  if (!strcmp(det, "PHOS")) fDetName.Form("%s_%02d", det, outerMod);
511  else fDetName.Form("%s_%02d%02d", det, fOuterRing, outerMod);
512  ntotal++;
513  npresent += (Int_t)CheckDetectorPresent(fDetName);
514  outerMod += fOuterDmod;
515  }
516  }
517  }
518  if (!npresent) Info("MakeRing", "\tBlock %d: ABSENT", i);
519  else if (npresent < ntotal) {
520  Info("MakeRing", "\tBlock %d: %d/%d detectors present", i, npresent, ntotal);
521  Info("MakeRing", "\tCASE NOT TREATED. ALL DETECTORS PRESENT.");
522  }
523  if (npresent) {
524 
525  if (fProtoDetector != oldProtoDet) {
526  // Prototype information has changed since last group/block
527  // We must create a new prototype
528 
529  Info("MakeRing", "DET:%s RING:%d Making new prototype group for i=%d/%d",
530  det, ring, i, Ndets);
531 
532  /* build and add frame */
533  MakeFrame(det, ring);
534 
535  // make pads in inner ring
537  PlaceDetector();
538  if (fInnerPads == 3) {
540  PlaceDetector();
541  TVector3 reflex[4];
543  TVector3 refcent;
544  CalculateCentre(reflex, refcent);
545  MakeDetector("A3", reflex, refcent);
546  PlaceDetector();
547  }
548  else {
549  if (fInnerPads == 2) {
550  TVector3 reflex[4];
552  TVector3 refcent;
553  CalculateCentre(reflex, refcent);
554  MakeDetector("A2", reflex, refcent);
555  PlaceDetector();
556  }
557  if (fOuterPads) {
558  // make pads in outer ring
560  PlaceDetector();
561  if (fOuterPads == 2) {
562  TVector3 reflex[4];
564  TVector3 refcent;
565  CalculateCentre(reflex, refcent);
566  MakeDetector("B2", reflex, refcent);
567  PlaceDetector();
568  }
569  }
570  }
571  }
572 
573  PlaceFrame(phi, i);
574  }
575 
576  if (((ring > 9 && ring < 13) && i == 1) || (ring > 12 && i == 2)) {
577  fEtalonTheta[ring - 10] = fFrameCentre.Theta() * TMath::RadToDeg();
578  fEtalonPhi[ring - 10] = phi;
580  fEtalonPhi[ring - 9] = phi;
581  }
582  phi += deltaPhi;
583  }
584 
585 }
586 
587 
588 
589 
592 
594 {
595 
596  // make volume corresponding to the actual detector
597 
598  TVector3 corners[8]; // 8 vertices of the volume
599  Double_t vertices[16];
600 
601  // Check whether this is a real multi-layer detector
602  // i.e. make sure all "layers" have non-zero thickness
603  Bool_t multi_layer = fLayers->GetSize() > 1;
604  if (multi_layer) {
605  TIter next(fLayers);
606  KVMaterial* abs;
607  Int_t no_abs = 0;
608  while ((abs = (KVMaterial*)next())) {
609  Double_t thick = abs->GetThickness();
610  if (thick > 0.0) no_abs++;
611  }
612  multi_layer = (no_abs > 1);
613  }
614  if (multi_layer) {
615  fDetVolume = gGeoManager->MakeVolumeAssembly(Form("DET_%s", det));
617  }
618  TVector3 frontPlane[4], backPlane[4], frontCentre, backCentre;
619  // front plane of first absorber is front plane of detector
620  for (int i = 0; i < 4; i++) frontPlane[i] = som[i];
621  frontCentre = cen;
622 
623  /**** BUILD & ADD LAYERS ****/
624  TIter next(fLayers);
625  KVMaterial* abs;
626  Double_t depth_in_det = 0.;
627  Int_t no_abs = 1;
628 
629  Double_t offX, offY; //offset of each layer
630  fDetectorPosition = 0;
631 
632  while ((abs = (KVMaterial*)next())) {
633  // get medium for absorber
634  TGeoMedium* med = abs->GetGeoMedium();
635  Double_t thick = abs->GetThickness();
636 
637  if (thick == 0.0) {
638  no_abs++; // ignore zero thickness layers
639  continue;
640  }
641 
642  // calculate coordinates of back plane
643  CalculateBackPlaneCoordinates(frontPlane, frontCentre, thick, backPlane);
644  // calculate centre of back plane
645  CalculateCentre(backPlane, backCentre);
646  // calculate corners of volume
647  TransformToOwnFrame(frontPlane, fFrameCentre, corners);
648  TransformToOwnFrame(backPlane, fFrameCentre, &corners[4]);
649  for (int i = 0; i < 8; i++) {
650  vertices[2 * i] = corners[i].X();
651  vertices[2 * i + 1] = corners[i].Y();
652  }
653 
654  Double_t dz = thick / 2.;
655  TString vol_name;
656  if (multi_layer) {
657  if (no_abs == fActiveLayer) vol_name = Form("ACTIVE_%s", det);
658  else vol_name = Form("%s_%d_%s", det, no_abs, abs->GetName());
659  }
660  else
661  vol_name = Form("DET_%s", det);
662  CorrectCoordinates(vertices, offX, offY);
663  TGeoVolume* vol =
664  gGeoManager->MakeArb8(vol_name.Data(), med, dz, vertices);
665  vol->SetLineColor(med->GetMaterial()->GetDefaultColor());
666  if (multi_layer) {
667  /*** position absorber in mother ***/
668  Double_t trans_z = -fTotalThickness / 2. + depth_in_det + dz; // (note: reference is CENTRE of absorber)
669  TGeoTranslation* tr = new TGeoTranslation(offX, offY, trans_z);
670  fDetVolume->AddNode(vol, no_abs, tr);
671  }
672  else {
673  // single absorber: mother is absorber is detector is mother is ...
674  fDetVolume = vol;
675  fDetectorPosition = new TGeoTranslation(offX, offY, 0);
676  }
677 
678  depth_in_det += thick;
679  no_abs++;
680 
681  // front of next absorber is back of current absorber
682  for (int i = 0; i < 4; i++) frontPlane[i] = backPlane[i];
683  frontCentre = backCentre;
684  }
685 }
686 
687 
688 
697 
699 {
700  // TVector3 corners[4] array of corner coordinates in usual order:
701  // corners[3] : theta-min, phi-min
702  // corners[2] : theta-max, phi-min
703  // corners[1] : theta-max, phi-max
704  // corners[0] : theta-min, phi-max
705  //
706  // Calculate the intersection of the normal to the plane passing through the origin.
707 
708  TVector3 a10 = corners[1] - corners[0];
709  TVector3 a21 = corners[2] - corners[1];
710  TVector3 normal = a10.Cross(a21);
711  Double_t d = (corners[3] * normal) / normal.Mag2();
712  inter = normal * d;
713 }
714 
715 
716 
717 
726 
728  Double_t thetamax, Double_t phimin, Double_t phimax, TVector3* corners)
729 {
730  // fill TVector3 corners[4] array in usual order:
731  // corners[3] : theta-min, phi-min
732  // corners[2] : theta-max, phi-min
733  // corners[1] : theta-max, phi-max
734  // corners[0] : theta-min, phi-max
735  // theta, phi in degrees
736  // These points lie in the plane defined by the equivalent TVEctor3 plane[4] corners
737 
738  TVector3 a10 = plane[1] - plane[0];
739  TVector3 a21 = plane[2] - plane[1];
740  TVector3 normal = a10.Cross(a21);
741  Double_t d0 = plane[3] * normal;
742 
743  TVector3 l;
744  l.SetMagThetaPhi(1., thetamin * TMath::DegToRad(), phimin * TMath::DegToRad());
745  corners[3] = l * (d0 / (l * normal));
746  l.SetMagThetaPhi(1., thetamax * TMath::DegToRad(), phimin * TMath::DegToRad());
747  corners[2] = l * (d0 / (l * normal));
748  l.SetMagThetaPhi(1., thetamax * TMath::DegToRad(), phimax * TMath::DegToRad());
749  corners[1] = l * (d0 / (l * normal));
750  l.SetMagThetaPhi(1., thetamin * TMath::DegToRad(), phimax * TMath::DegToRad());
751  corners[0] = l * (d0 / (l * normal));
752 }
753 
754 
755 
757 
759 {
761  //gGeoManager->GetTopVolume()->SetVisContainers();
763  gGeoManager->GetTopVolume()->Draw("ogl");
764 }
765 
766 
767 
769 
771 {
772  for (int i = 0; i < 4; i++) {
773  newpad[3 - i].SetMagThetaPhi(orig[i].Mag(), orig[i].Theta(), 2.*phicentre - orig[i].Phi());
774  }
775 }
776 
777 
778 
782 
784 {
785  //TO DO: multi-layer targets + target with angle to beam
786 
787  // target holder
788  KVMaterial target_holder_mat("Al");
789  new TGeoBBox("TARGET_FRAME", 3., 3., 0.1 / 2.);
790  new TGeoEltu("TARGET_HOLE", 2., 2., 0.1 / 2.);
791  TGeoCompositeShape* cs = new TGeoCompositeShape("TARGET_FRAME", "TARGET_FRAME - TARGET_HOLE");
792  TGeoVolume* target_frame = new TGeoVolume("TARGET_FRAME", cs, target_holder_mat.GetGeoMedium());
793  gGeoManager->GetTopVolume()->AddNode(target_frame, 1);
794 
795  // add target
796  // only single-layer target treated correctly
797  KVTarget* T = gIndra->GetTarget();
798  if (T) {
799  KVMaterial* targMat = (KVMaterial*)T->GetLayers()->First();
800  TGeoVolume* target = gGeoManager->MakeEltu("TARGET", targMat->GetGeoMedium(), 2., 2., targMat->GetThickness() / 2.);
802  }
803 }
804 
805 
806 
808 
809 void INDRAGeometryBuilder::Build(Bool_t withTarget, Bool_t closeGeometry)
810 {
811  if (!gIndra) {
812  Error("Build", "You must build the geometry with gDataSet->BuildMultiDetector() before calling this method");
813  return;
814  }
815 
816  if (!gGeoManager) {
817  Error("Build", "You must defined gGeoManager with KVMultiDetArray::CreateGeoManager before calling this method");
818  return;
819  }
820 
821  if (gIndra->GetDetector("PHOS_01")) MakeRing("PHOS", 1);
822  else {
823  MakeRing("SI", 1);
824  MakeRing("CSI", 1);
825  }
826  for (int ring = 2; ring <= 16; ring += 2) {
827  MakeRing("CI", ring);
828  if (ring > 1 && ring < 10)MakeRing("SI", ring);
829  MakeRing("CSI", ring);
830  if (ring == 12) {
831  MakeRing("CI", ring + 1);
832  MakeRing("CSI", ring + 1);
833  }
834  }
835  for (int ring = 10; ring <= 17; ring++) {
836  if (gIndra->GetDetector(Form("SI75_%d", ring))) MakeEtalon(ring);
837  }
838  if (withTarget) BuildTarget();
839  if (closeGeometry) {
842  }
843 
844 }
845 
846 
866 
867 void INDRAGeometryBuilder::Build(const KVNumberList& rings, const KVNameValueList& detectors)
868 {
869  // Build geometry, using only the ring numbers in the KVNumberList, and
870  // only the detectors which are in the KVNameValueList:
871  //
872  // KVNameValueList dets;
873  // dets.SetValue("CI",1);
874  // dets.SetValue("SI",1);
875  // igb.Build("2-9", dets); // use INDRAGeometryBuilder object 'igb' to build
876  // // ChIo and Silicon detectors of rings 2-9
877  //
878  // Possible detector types are "CI", "SI", "CSI", "PHOS"
879  // If you want to see the target in the previous example, use dets.SetValue("TARGET",1)
880  //
881  // Include "ring+100" in number list to build etalon telescope for "ring"
882  //
883  // This method will not destroy any pre-existing geometry (gGeoManager),
884  // but will create one if none exists.
885  // Also it will not close the geometry, leaving the possibility to add ancillary
886  // detectors.
887 
888  if (!gIndra) {
889  Error("Build", "You must build the geometry with gDataSet->BuildMultiDetector() before calling this method");
890  return;
891  }
892 
893  if (!gGeoManager) {
894  Error("Build", "You must defined gGeoManager with KVMultiDetArray::CreateGeoManager before calling this method");
895  return;
896  }
897 
898  if (rings.Contains(1)) {
899  if (detectors.HasParameter("PHOS")) MakeRing("PHOS", 1);
900  if (detectors.HasParameter("SI"))MakeRing("SI", 1);
901  if (detectors.HasParameter("CSI"))MakeRing("CSI", 1);
902  }
903  for (int ring = 2; ring <= 16; ring += 2) {
904  if (rings.Contains(ring) && detectors.HasParameter("CI")) MakeRing("CI", ring);
905  if (ring > 1 && ring < 10) {
906  if (rings.Contains(ring) && detectors.HasParameter("SI"))MakeRing("SI", ring);
907  }
908  if (rings.Contains(ring) && detectors.HasParameter("CSI"))MakeRing("CSI", ring);
909  if (ring == 12) {
910  if (rings.Contains(ring + 1) && detectors.HasParameter("CI"))MakeRing("CI", ring + 1);
911  if (rings.Contains(ring + 1) && detectors.HasParameter("CSI"))MakeRing("CSI", ring + 1);
912  }
913  }
914  for (int ring = 10; ring <= 17; ring++) {
915  if (rings.Contains(ring + 100)) MakeEtalon(ring);
916  }
917 
918  if (detectors.HasParameter("TARGET"))
919  BuildTarget();
920 }
921 
922 
923 
925 
926 void INDRAGeometryBuilder::BuildEtalonVolumes()
927 {
928  KVMaterial mat_si("Si");
929  KVMaterial mat_li("Li");
930  KVMaterial mat_al("Al");
931  TGeoMedium* Silicon = mat_si.GetGeoMedium();
932  TGeoMedium* Lithium = mat_li.GetGeoMedium();
933  TGeoMedium* Alu = mat_al.GetGeoMedium();
934 
935  Double_t sili_diameter_total = 2.54;
936  Double_t holder_thickness = 0.05;
937  Double_t holder_length = 1.0;
938  Double_t sili_diameter_active = 2.36;
939  Double_t sili_silicon_thickness = 0.22;
940  Double_t sili_lithium_thickness = 0.0044;
941  Double_t si75_thickness = 0.008;
942  Double_t si75_diameter_active = 2.2;
943 
944  fEtalonVol = new TGeoVolumeAssembly("STRUCT_ETALON");
946 
947  TGeoVolume* holder = gGeoManager->MakeTube("DEADZONE_ETALON_HOLDER", Alu,
948  (sili_diameter_total) / 2., (sili_diameter_total + 2 * holder_thickness) / 2., holder_length / 2.);
949  holder->SetLineColor(holder->GetMaterial()->GetDefaultColor());
950  fEtalonVol->AddNode(holder, 1);
951 
952  Double_t w = sili_silicon_thickness + sili_lithium_thickness;
953  TGeoVolume* sili_dz = gGeoManager->MakeTube("DEADZONE_SILI", Alu,
954  sili_diameter_active / 2., (sili_diameter_total) / 2., w / 2.);
955  sili_dz->SetLineColor(sili_dz->GetMaterial()->GetDefaultColor());
956 
957  fEtalonVol->AddNode(sili_dz, 1, new TGeoTranslation(0, 0, holder_length / 4.));
958 
959  TGeoVolumeAssembly* sili = new TGeoVolumeAssembly("DET_SILI");
960  sili->SetMedium(gGeoManager->GetMedium("Vacuum"));
961  TGeoVolume* sili_si = gGeoManager->MakeTube("ACTIVE_SILI", Silicon,
962  0., (sili_diameter_active) / 2., (sili_silicon_thickness) / 2.);
963  TGeoVolume* sili_li = gGeoManager->MakeTube("SILI_LI", Lithium,
964  0., (sili_diameter_active) / 2., (sili_lithium_thickness) / 2.);
965  sili_si->SetLineColor(sili_si->GetMaterial()->GetDefaultColor());
966  sili_li->SetLineColor(sili_li->GetMaterial()->GetDefaultColor());
967  sili->AddNode(sili_si, 1, new TGeoTranslation(0, 0, -(w / 2. - sili_silicon_thickness / 2.)));
968  sili->AddNode(sili_li, 1, new TGeoTranslation(0, 0, w / 2. - sili_lithium_thickness / 2.));
969  fEtalonVol->AddNode(sili, 1, new TGeoTranslation(0, 0, holder_length / 4.));
970 
971  TGeoVolume* si75 = gGeoManager->MakeTube("DET_SI75", Silicon,
972  0., (si75_diameter_active) / 2., (si75_thickness) / 2.);
973  TGeoVolume* si75_dz = gGeoManager->MakeTube("DEADZONE_SI75", Alu,
974  (si75_diameter_active) / 2., (sili_diameter_total) / 2., (si75_thickness) / 2.);
975 
976  fEtalonVol->AddNode(si75_dz, 1);
977  fEtalonVol->AddNode(si75, 1);
978 
979 }
980 
981 
982 
987 
989 {
990  // Build and add etalon telescope for ring
991  //Double_t theta[] = {51.075000,63.340000,79.435000,100.685000,118.235000,133.905000,149.790000,166.435000};
992  //Double_t phi[] = {37.500000,37.500000,37.500000,90.000000,78.750000,78.750000,90.000000,90.000000};
993  Double_t dist[] = {17.4005, 17.4005, 17.4005, 16.7005, 16.7005, 16.7005, 17.4005, 17.4005,};
994 
995  if (!fEtalonVol) BuildEtalonVolumes();
996 
997  cout << "Etalons " << RING << " : " << fEtalonTheta[RING - 10] << " " << fEtalonPhi[RING - 10] << endl;
998  TGeoTranslation trans;
999  trans.SetDz(dist[RING - 10]);
1000  TGeoRotation rot1, rot2;
1001  TGeoHMatrix h;
1002  TGeoHMatrix* ph = 0;
1003 
1004 // rot2.SetAngles(phi[RING-10]+90., theta[RING-10], 0.);
1005 // rot1.SetAngles(-1.*phi[RING-10], 0., 0.);
1006  rot2.SetAngles(fEtalonPhi[RING - 10] + 90., fEtalonTheta[RING - 10], 0.);
1007  rot1.SetAngles(-1.*fEtalonPhi[RING - 10], 0., 0.);
1008 // if(RING==13){
1009 // TGeoTranslation p(4.5,0,0);
1010 // h = p * rot2 * trans * rot1;
1011 // }
1012  if (RING == 10) {
1013  TGeoTranslation p(1.5, 2.5, 0);
1014  h = rot2 * trans * p * rot1;
1015  }
1016  else if (RING == 11) {
1017  TGeoTranslation p(1.5, -1.5, 0);
1018  h = rot2 * trans * p * rot1;
1019  }
1020  else if (RING == 12) {
1021  TGeoTranslation p(1.5, 0, 0);
1022  h = rot2 * trans * p * rot1;
1023  }
1024  else if (RING == 13) {
1025  TGeoTranslation p(-4, -0.5, 0);
1026  h = rot2 * trans * p * rot1;
1027  }
1028  else if (RING == 14) {
1029  TGeoTranslation p(-1.7, 1.75, 0);
1030  h = rot2 * trans * p * rot1;
1031  }
1032  else if (RING == 15) {
1033  TGeoTranslation p(-1.7, -3, 0);
1034  h = rot2 * trans * p * rot1;
1035  }
1036  else if (RING == 16) {
1037  TGeoTranslation p(0, 2.5, 0);
1038  h = rot2 * trans * p * rot1;
1039  }
1040  else {
1041  TGeoTranslation p(0, -2.25, 0);
1042  h = rot2 * trans * p * rot1;
1043  }
1044  ph = new TGeoHMatrix(h);
1045  gGeoManager->GetTopVolume()->AddNode(fEtalonVol, RING, ph);
1046 }
1047 
1048 
int Int_t
#define d(i)
bool Bool_t
char Char_t
constexpr Bool_t kFALSE
double Double_t
constexpr Bool_t kTRUE
const char Option_t
kEnvAll
winID w
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t target
R__EXTERN TGeoManager * gGeoManager
char * Form(const char *fmt,...)
Build INDRA geometry from Huguet CAO infos.
void CorrectCoordinates(Double_t *, Double_t &, Double_t &)
void MakeDetector(const Char_t *det, TVector3 *som, TVector3 cen)
make volume corresponding to the actual detector
INDRAGeometryBuilder()
Default constructor.
Int_t Ndets
number of detectors in ring
void Copy(TObject &) const
void CalculateBackPlaneCoordinates(TVector3 *frontcoords, TVector3 centre, Double_t depth, TVector3 *backcoords)
TGeoVolume * fDetVolume
geo volume representing frame
void CalculateCentre(TVector3 *corners, TVector3 &centre)
Double_t fTotalThickness
sum of thicknesses of layers of current detector
void ReadDetCAO(const Char_t *detname, Int_t ring)
Int_t fActiveLayer
index of active layer of current detector
TString fDetName
name of detector
TVector3 fInnerCentre
centre of inner face
void PlaceFrame(Double_t phi, Int_t copy_no)
position frame (dead zone) volume in geometry
KVMaterial fFrameMat
material of outer frame
void ReflectPad(TVector3 *orig, Double_t phicentre, TVector3 *newpad)
Double_t phi0
theoretical geometry
TVector3 fInnerFront[4]
coords of inner front face
void CalculateCornersInPlane(TVector3 *plane, Double_t thetamin, Double_t thetamax, Double_t phimin, Double_t phimax, TVector3 *corners)
TVector3 fOuterFront[4]
coords of outer front face
TVector3 fOuterCentre
centre of outer face
void Print(Option_t *="") const
Bool_t CheckDetectorPresent(TString detname)
void TransformToOwnFrame(TVector3 *orig, TVector3 &centre, TVector3 *ownframe)
KVDetector * fProtoDetector
detector used for last fLayers look up
TVector3 fFrameFront[4]
coords of outer front face
virtual ~INDRAGeometryBuilder()
Destructor.
void Build(Bool_t withTarget=kTRUE, Bool_t closeGeometry=kTRUE)
void MakeRing(const Char_t *det, int ring)
KVList * fLayers
list of materials making up layers of current detector
void MakeFrame(TString det_type, Int_t ring_num)
TVector3 fFrameCentre
centre of frame
TGeoVolume * fFrameVolume
geo volume representing frame
void PlaceDetector()
position detector inside frame
TGeoTranslation * fDetectorPosition
TGeoVolumeAssembly * fEtalonVol
Base class for KaliVeda framework.
Definition: KVBase.h:142
static Bool_t SearchKVFile(const Char_t *name, TString &fullpath, const Char_t *kvsubdir="")
Definition: KVBase.cpp:538
Base class for detector geometry description.
Definition: KVDetector.h:160
Bool_t HasSameStructureAs(const KVDetector *) const
Double_t GetTotalThicknessInCM()
Definition: KVDetector.h:315
KVMaterial * GetActiveLayer() const
Definition: KVDetector.h:290
KVList * GetListOfAbsorbers() const
Definition: KVDetector.h:301
virtual Bool_t IsPresent() const
Definition: KVDetector.h:663
KVDetector * GetDetector(const Char_t *name) const
Return detector in this structure with given name.
Description of physical materials used to construct detectors & targets; interface to range tables.
Definition: KVMaterial.h:94
virtual Double_t GetThickness() const
Definition: KVMaterial.cpp:487
virtual TGeoMedium * GetGeoMedium(const Char_t *="")
virtual void SetMaterial(const Char_t *type)
Definition: KVMaterial.cpp:225
KVTarget * GetTarget()
Handles lists of named parameters with different types, a list of KVNamedParameter objects.
Bool_t HasParameter(const Char_t *name) const
Strings used to represent a set of ranges of values.
Definition: KVNumberList.h:85
Bool_t Contains(Int_t val) const
returns kTRUE if the value 'val' is contained in the ranges defined by the number list
virtual Int_t GetSize() const
Calculation/correction of energy losses of particles through an experimental target.
Definition: KVTarget.h:127
virtual const char * GetValue(const char *name, const char *dflt) const
virtual Int_t ReadFile(const char *fname, EEnvLevel level)
TGeoVolume * MakeTube(const char *name, TGeoMedium *medium, Double_t rmin, Double_t rmax, Double_t dz)
TGeoVolume * MakeArb8(const char *name, TGeoMedium *medium, Double_t dz, Double_t *vertices=nullptr)
void CloseGeometry(Option_t *option="d")
void DefaultColors()
TGeoMedium * GetMedium(const char *medium) const
TGeoVolumeAssembly * MakeVolumeAssembly(const char *name)
TGeoVolume * GetTopVolume() const
TGeoVolume * MakeEltu(const char *name, TGeoMedium *medium, Double_t a, Double_t b, Double_t dz)
virtual Int_t GetDefaultColor() const
TGeoMaterial * GetMaterial() const
void SetAngles(Double_t phi, Double_t theta, Double_t psi)
void SetDz(Double_t dz) override
TGeoNode * AddNode(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat=nullptr, Option_t *option="") override
virtual TGeoNode * AddNode(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat=nullptr, Option_t *option="")
void Draw(Option_t *option="") override
TGeoMaterial * GetMaterial() const
TGeoNode * GetNode(const char *name) const
virtual void SetMedium(TGeoMedium *medium)
void SetLineColor(Color_t lcolor) override
const char * GetName() const override
const char * GetTitle() const override
virtual void SetName(const char *name)
virtual void Copy(TObject &object) const
virtual void Error(const char *method, const char *msgfmt,...) const
virtual void Info(const char *method, const char *msgfmt,...) const
TRotation & SetYEulerAngles(Double_t phi, Double_t theta, Double_t psi)
virtual Int_t IndexOf(const TObject *obj) const
const char * Data() const
void Form(const char *fmt,...)
void SetMagThetaPhi(Double_t mag, Double_t theta, Double_t phi)
void SetY(Double_t)
void Print(Option_t *option="") const override
Double_t Phi() const
Double_t Y() const
void RotateZ(Double_t)
Double_t Mag2() const
Double_t X() const
Double_t Mag() const
Double_t Theta() const
void SetX(Double_t)
TVector3 Cross(const TVector3 &) const
void SetZ(Double_t)
T Mag(const SVector< T, D > &rhs)
RVec< PromoteType< T > > abs(const RVec< T > &v)
TH1 * h
double T(double x)
double dist(AxisAngle const &r1, AxisAngle const &r2)
constexpr Double_t DegToRad()
constexpr Double_t RadToDeg()
TLine l
ClassImp(TPyArg)