KaliVeda
Toolkit for HIC analysis
Loading...
Searching...
No Matches
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
18using namespace std;
19
21
22
23
27
28void 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
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++) {
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++) {
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.,
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
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
386void 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
538 if (fInnerPads == 3) {
541 TVector3 reflex[4];
543 TVector3 refcent;
544 CalculateCentre(reflex, refcent);
545 MakeDetector("A3", reflex, refcent);
547 }
548 else {
549 if (fInnerPads == 2) {
550 TVector3 reflex[4];
552 TVector3 refcent;
553 CalculateCentre(reflex, refcent);
554 MakeDetector("A2", reflex, refcent);
556 }
557 if (fOuterPads) {
558 // make pads in outer ring
561 if (fOuterPads == 2) {
562 TVector3 reflex[4];
564 TVector3 refcent;
565 CalculateCentre(reflex, refcent);
566 MakeDetector("B2", reflex, refcent);
568 }
569 }
570 }
571 }
572
573 PlaceFrame(phi, i);
574 }
575
576 if (((ring > 9 && ring < 13) && i == 1) || (ring > 12 && i == 2)) {
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);
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) {
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);
626 Double_t depth_in_det = 0.;
627 Int_t no_abs = 1;
628
629 Double_t offX, offY; //offset of each layer
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);
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
809void 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
867void 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
926void 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);
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
KVList * GetListOfAbsorbers() const
Definition KVDetector.h:301
KVMaterial * GetActiveLayer() const
Definition KVDetector.h:290
Bool_t HasSameStructureAs(const KVDetector *) const
Double_t GetTotalThicknessInCM()
Definition KVDetector.h:315
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
virtual TGeoMedium * GetGeoMedium(const Char_t *="")
virtual void SetMaterial(const Char_t *type)
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.
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)