SND@LHC Software
Loading...
Searching...
No Matches
Scifi.cxx
Go to the documentation of this file.
1#include "Scifi.h"
2#include "ScifiPoint.h"
3
4#include "TGeoManager.h"
5#include "FairRun.h" // for FairRun
6#include "FairRuntimeDb.h" // for FairRuntimeDb
7#include "TList.h" // for TListIter, TList (ptr only)
8#include "TObjArray.h" // for TObjArray
9#include "TString.h" // for TString
10
11#include "TClonesArray.h"
12#include "TVirtualMC.h"
13
14#include "TGeoBBox.h"
15#include "TGeoTrd1.h"
16#include "TGeoCompositeShape.h"
17#include "TGeoTube.h"
18#include "TGeoMaterial.h"
19#include "TGeoMedium.h"
20#include "TParticle.h"
21
22#include "FairVolume.h"
23#include "FairGeoVolume.h"
24#include "FairGeoNode.h"
25#include "FairRootManager.h"
26#include "FairGeoLoader.h"
27#include "FairGeoInterface.h"
28#include "FairGeoMedia.h"
29#include "FairGeoBuilder.h"
30#include "FairRun.h"
31#include "FairRuntimeDb.h"
32
33#include "ShipDetectorList.h"
34#include "ShipUnit.h"
35#include "ShipStack.h"
36
37#include "TGeoUniformMagField.h"
38#include <stddef.h> // for NULL
39#include <iostream> // for operator<<, basic_ostream, etc
40
41using std::cout;
42using std::endl;
43
44using namespace ShipUnit;
45
47: FairDetector("Scifi", "", kTRUE),
48fTrackID(-1),
49fVolumeID(-1),
50fPos(),
51fMom(),
52fTime(-1.),
53fLength(-1.),
54fELoss(-1),
55eventHeader(0),
56last_run_time(-1),
57last_run_pos(-1),
58last_time_alignment_tag(""),
59last_position_alignment_tag(""),
60alignment_init(false),
61fScifiPointCollection(new TClonesArray("ScifiPoint"))
62{
63}
64
65Scifi::Scifi(const char* name, Bool_t Active, const char* Title)
66: FairDetector(name, true, kLHCScifi),
67fTrackID(-1),
68fVolumeID(-1),
69fPos(),
70fMom(),
71fTime(-1.),
72fLength(-1.),
73fELoss(-1),
74eventHeader(0),
75last_run_time(-1),
76last_run_pos(-1),
77last_time_alignment_tag(""),
78last_position_alignment_tag(""),
79alignment_init(false),
80fScifiPointCollection(new TClonesArray("ScifiPoint"))
81{
82}
83
85{
87 fScifiPointCollection->Delete();
89 }
90}
91
93{
94 FairDetector::Initialize();
95}
96
97// ----- Private method InitMedium
98Int_t Scifi::InitMedium(const char* name)
99{
100 static FairGeoLoader *geoLoad=FairGeoLoader::Instance();
101 static FairGeoInterface *geoFace=geoLoad->getGeoInterface();
102 static FairGeoMedia *media=geoFace->getMedia();
103 static FairGeoBuilder *geoBuild=geoLoad->getGeoBuilder();
104
105 FairGeoMedium *ShipMedium=media->getMedium(name);
106
107 if (!ShipMedium)
108 {
109 Fatal("InitMedium","Material %s not defined in media file.", name);
110 return -1111;
111 }
112 TGeoMedium* medium=gGeoManager->GetMedium(name);
113 if (medium!=NULL)
114 return ShipMedium->getMediumIndex();
115 return geoBuild->createMedium(ShipMedium);
116}
117
119{
120 InitMedium("CarbonComposite");
121 TGeoMedium *CarbonComposite = gGeoManager->GetMedium("CarbonComposite");
122
123 InitMedium("rohacell");
124 TGeoMedium *rohacell = gGeoManager->GetMedium("rohacell");
125
126 InitMedium("air");
127 TGeoMedium *air = gGeoManager->GetMedium("air");
128
129 InitMedium("Polycarbonate");
130 TGeoMedium *PlasticBase = gGeoManager->GetMedium("Polycarbonate");
131
132 InitMedium("Polystyrene");
133 TGeoMedium *Polystyrene = gGeoManager->GetMedium("Polystyrene");
134
135 InitMedium("PMMA");
136 TGeoMedium *PMMA = gGeoManager->GetMedium("PMMA");
137
138 InitMedium("PMMA2");
139 TGeoMedium *PMMA2 = gGeoManager->GetMedium("PMMA2");
140
141 InitMedium("Epoxy");
142 TGeoMedium *Epoxy = gGeoManager->GetMedium("Epoxy");
143
144 TGeoVolume *volTarget = gGeoManager->GetVolume("volTarget");
145
146 InitMedium("iron");
147 TGeoMedium *Fe =gGeoManager->GetMedium("iron");
148
149// external parameters
150 Double_t fXDimension = conf_floats["Scifi/xdim"];
151 Double_t fYDimension = conf_floats["Scifi/ydim"];
152 Double_t fZDimension = conf_floats["Scifi/zdim"];
153
154 Double_t fWidthScifiMat = conf_floats["Scifi/scifimat_width"];
155 Double_t fLengthScifiMat = conf_floats["Scifi/scifimat_length"];
156 Double_t fZScifiMat = conf_floats["Scifi/scifimat_z"];
157 Double_t fZEpoxyMat = conf_floats["Scifi/epoxymat_z"];
158 Double_t fGapScifiMat = conf_floats["Scifi/scifimat_gap"]; //dead zone between mats
159
160 Double_t fFiberLength = conf_floats["Scifi/fiber_length"];
161 Double_t fScintCore_rmax = conf_floats["Scifi/scintcore_rmax"];
162 Double_t fClad1_rmin = conf_floats["Scifi/clad1_rmin"];
163 Double_t fClad1_rmax = conf_floats["Scifi/clad1_rmax"];
164 Double_t fClad2_rmin = conf_floats["Scifi/clad2_rmin"];
165 Double_t fClad2_rmax = conf_floats["Scifi/clad2_rmax"];
166
167 Double_t fHorPitch = conf_floats["Scifi/horizontal_pitch"]; //Fiber position params
168 Double_t fVertPitch = conf_floats["Scifi/vertical_pitch"];
169 Double_t fOffsetRowS = conf_floats["Scifi/rowlong_offset"];
170 Double_t fOffsetRowL = conf_floats["Scifi/rowshort_offset"];
171
172 Double_t fZCarbonFiber = conf_floats["Scifi/carbonfiber_z"];
173 Double_t fZHoneycomb = conf_floats["Scifi/honeycomb_z"];
174
175 Double_t fXPlastBar = conf_floats["Scifi/plastbar_x"]; //Dimension of plastic bar
176 Double_t fYPlastBar = conf_floats["Scifi/plastbar_y"];
177 Double_t fZPlastBar = conf_floats["Scifi/plastbar_z"];
178
179 Int_t fNFibers_Srow = conf_ints["Scifi/nfibers_shortrow"];
180 Int_t fNFibers_Lrow = conf_ints["Scifi/nfibers_longrow"];
181 Int_t fNFibers_z = conf_ints["Scifi/nfibers_z"];
182
183 Double_t fSeparationBrick = conf_floats["Scifi/scifi_separation"]; //Separation between successive SciFi volumes
184 Double_t fZOffset = conf_floats["Scifi/offset_z"];
185 Int_t fNMats = conf_ints["Scifi/nmats"]; //Number of mats in one SciFi plane
186 Int_t fNScifi = conf_ints["Scifi/nscifi"]; //Number of Scifi walls
187 Int_t fNSiPMs = conf_ints["Scifi/nsipm_mat"]; //Number of SiPMs per SciFi mat
188
189 Double_t fWidthChannel = conf_floats["Scifi/channel_width"]; //One channel width
190 Double_t fCharr = conf_floats["Scifi/charr_width"]; //Width of an array of 64 channels without gaps
191 Double_t fEdge = conf_floats["Scifi/sipm_edge"]; //Edge at the left and right sides of the SiPM
192 Double_t fCharrGap = conf_floats["Scifi/charr_gap"]; //Gap between two charr
193 Double_t fBigGap = conf_floats["Scifi/sipm_diegap"]; //Gap between two arrays
194 Int_t fNSiPMChan = conf_ints["Scifi/nsipm_channels"]; //Number of channels in each SiPM
195 Double_t firstChannelX = conf_floats["Scifi/firstChannelX"]; //local X Position of first channel in plane
196
197//edge positions in TI18 survey system:
198 std::map<int,TVector3> Vedges;
199 Vedges[0]=TVector3(-conf_floats["Scifi/Xpos0"],conf_floats["Scifi/Zpos0"],conf_floats["Scifi/Ypos0"]);
200 Vedges[1]=TVector3(-conf_floats["Scifi/Xpos1"],conf_floats["Scifi/Zpos1"],conf_floats["Scifi/Ypos1"]);
201 Vedges[2]=TVector3(-conf_floats["Scifi/Xpos2"],conf_floats["Scifi/Zpos2"],conf_floats["Scifi/Ypos2"]);
202 Vedges[3]=TVector3(-conf_floats["Scifi/Xpos3"],conf_floats["Scifi/Zpos3"],conf_floats["Scifi/Ypos3"]);
203 Vedges[4]=TVector3(-conf_floats["Scifi/Xpos4"],conf_floats["Scifi/Zpos4"],conf_floats["Scifi/Ypos4"]);
204
205//edge position in Scifi engineering drawing, y down, z towards IP1, pos X left.
206// need y up, z away from IP1, pos X left: y and z need to change sign.
207
208 TVector3 Sedge = TVector3(conf_floats["Scifi/EdgeAX"],-conf_floats["Scifi/EdgeAY"],-conf_floats["Scifi/EdgeAZ"]);
209//first channel position in Scifi engineering drawing:
210 TVector3 SHfirst = TVector3(conf_floats["Scifi/FirstChannelHX"],-conf_floats["Scifi/FirstChannelHY"],-conf_floats["Scifi/FirstChannelHZ"]);
211 TVector3 SVfirst = TVector3(conf_floats["Scifi/FirstChannelVX"],-conf_floats["Scifi/FirstChannelVY"],-conf_floats["Scifi/FirstChannelVZ"]);
212
213//first channel position in sndsw local plane:
214 TVector3 LHfirst = TVector3(conf_floats["Scifi/LfirstChannelHX"],conf_floats["Scifi/LfirstChannelHY"],conf_floats["Scifi/LfirstChannelHZ"]);
215 TVector3 LVfirst = TVector3(conf_floats["Scifi/LfirstChannelVX"],conf_floats["Scifi/LfirstChannelVY"],conf_floats["Scifi/LfirstChannelVZ"]);
216// moving plane to match edges:
217 std::map<int,TVector3> DeltasH;
218 std::map<int,TVector3> DeltasV;
219 for (int i=0;i<5;i++){
220 DeltasH[i] = Vedges[i] - LHfirst + SHfirst - Sedge;
221 DeltasV[i] = Vedges[i] - LVfirst + SVfirst - Sedge;
222 }
223
224 //Carbon Fiber Film
225 TGeoVolume *CarbonFiberVolume = gGeoManager->MakeBox("CarbonFiber", CarbonComposite, fXDimension/2, fYDimension/2, fZCarbonFiber/2);
226 CarbonFiberVolume->SetLineColor(kGray - 2);
227 CarbonFiberVolume->SetVisibility(1);
228
229 //Honeycomb Rohacell
230 TGeoVolume *HoneycombVolume = gGeoManager->MakeBox("Honeycomb", rohacell, fXDimension/2, fYDimension/2, fZHoneycomb/2);
231 HoneycombVolume->SetLineColor(kYellow);
232 HoneycombVolume->SetVisibility(1);
233
234 //Plastic/Air
235 //Definition of the box containing polycarbonate pieces and an air gap
236 TGeoVolume *PlasticAirVolume = gGeoManager->MakeBox("PlasticAir", air, fXDimension/2, fYDimension/2, fZPlastBar/2);
237 PlasticAirVolume->SetLineColor(kGray-1);
238 PlasticAirVolume->SetVisibility(1);
239 PlasticAirVolume->SetVisDaughters(1);
240
241 //Plastic bars
242 TGeoVolume *PlasticBarVolume = gGeoManager->MakeBox("PlasticBar", PlasticBase, fXPlastBar/2, fYPlastBar/2, fZPlastBar/2);
243 PlasticBarVolume->SetLineColor(kGray-4);
244 PlasticBarVolume->SetVisibility(1);
245
246 PlasticAirVolume->AddNode(PlasticBarVolume, 0, new TGeoTranslation(- fXDimension/2 + fXPlastBar/2, 0, 0)); //bars are placed || to y
247 PlasticAirVolume->AddNode(PlasticBarVolume, 1, new TGeoTranslation(+ fXDimension/2 - fXPlastBar/2, 0, 0));
248
249 //Fiber volume that contains the scintillating core and double cladding
250 TGeoVolumeAssembly *FiberVolume = new TGeoVolumeAssembly("FiberVolume");
251
252 TGeoVolume *ScintCoreVol = gGeoManager->MakeTube("ScintCoreVol", Polystyrene, 0, fScintCore_rmax, fFiberLength/2);
253 TGeoVolume *Clad1Vol = gGeoManager->MakeTube("Clad1Vol", PMMA, fClad1_rmin, fClad1_rmax, fFiberLength/2);
254 TGeoVolume *Clad2Vol = gGeoManager->MakeTube("Clad2Vol", PMMA2, fClad2_rmin, fClad2_rmax, fFiberLength/2);
255
256 FiberVolume->AddNode(ScintCoreVol, 0);
257 FiberVolume->AddNode(Clad1Vol, 0);
258 FiberVolume->AddNode(Clad2Vol, 0);
259 FiberVolume->SetVisDaughters(kFALSE);
260
261 //Add SciFi fiber as sensitive unit
262 AddSensitiveVolume(ScintCoreVol);
263
264 //Fiber and plane rotations
265 TGeoRotation *rothorfiber = new TGeoRotation("rothorfiber", 90, 90, 0);
266 TGeoRotation *rotvertfiber = new TGeoRotation("rotvertfiber", 0, 90, 0);
267 TGeoRotation *rot = new TGeoRotation("rot", 90, 180, 0);
268
269 //SciFi mats for X and Y fiber planes
270 TGeoVolume *HorMatVolume = gGeoManager->MakeBox("HorMatVolume", Epoxy, fLengthScifiMat/2, fWidthScifiMat/2, fZEpoxyMat/2);
271 TGeoVolume *VertMatVolume = gGeoManager->MakeBox("VertMatVolume", Epoxy, fWidthScifiMat/2, fLengthScifiMat/2, fZEpoxyMat/2);
272
273 Double_t zPosM;
274 Double_t offsetS = -fWidthScifiMat/2 + fOffsetRowS;
275 Double_t offsetL = -fWidthScifiMat/2 + fOffsetRowL;
276
277 // All fibres will be assigned station number 1 and mat number 1, to keep compatibility with the STMRFFF format.
278 int dummy_station = 1;
279 int dummy_mat = 1;
280
281 //Adding horizontal fibers
282 for (int irow = 0; irow < fNFibers_z; irow++){
283 zPosM = -fZScifiMat/2 + fClad2_rmax/2 + irow*fVertPitch;
284 if (irow%2 == 0){
285 for (int ifiber = 0; ifiber < fNFibers_Srow; ifiber++){
286 HorMatVolume->AddNode(FiberVolume, 1e6*dummy_station + 1e5*0 + 1e4*dummy_mat + 1e3*(irow + 1) + ifiber + 1, new TGeoCombiTrans("rottranshor0", 0, offsetS + ifiber*fHorPitch, zPosM, rothorfiber));
287 }
288 }
289 else{
290 for (int ifiber = 0; ifiber < fNFibers_Lrow; ifiber++){
291 HorMatVolume->AddNode(FiberVolume, 1e6*dummy_station + 1e5*0 + 1e4*dummy_mat + 1e3*(irow + 1) + ifiber + 1, new TGeoCombiTrans("rottranshor1", 0, offsetL + ifiber*fHorPitch, zPosM, rothorfiber));
292 }
293 }
294 }
295
296 //Adding vertical fibers
297 for (int irow = 0; irow < fNFibers_z; irow++){
298 zPosM = -fZScifiMat/2 + fClad2_rmax/2 + irow*fVertPitch;
299 if (irow%2 == 0){
300 for (int ifiber = 0; ifiber < fNFibers_Srow; ifiber++){
301 VertMatVolume->AddNode(FiberVolume, 1e6*dummy_station + 1e5*1 + 1e4*dummy_mat + 1e3*(irow + 1) + ifiber + 1, new TGeoCombiTrans("rottransvert0", offsetS + ifiber*fHorPitch, 0, zPosM, rotvertfiber));
302 }
303 }
304 else{
305 for (int ifiber = 0; ifiber < fNFibers_Lrow; ifiber++){
306 VertMatVolume->AddNode(FiberVolume, 1e6*dummy_station + 1e5*1 + 1e4*dummy_mat + 1e3*(irow + 1) + ifiber + 1, new TGeoCombiTrans("rottransvert1", offsetL + ifiber*fHorPitch, 0, zPosM, rotvertfiber));
307 }
308 }
309 }
310
311 // for testbeam 2023
312 // for now the distinct feature of the testbeam could be the 4 SciFi planes
313 std::map<int, TGeoVolume*> volFeTarget;
314 std::map<int, float> fFeTargetX;
315 std::map<int, float> fFeTargetY;
316 std::map<int, float> fFeTargetZ;
317 for ( int i = 0; i < fNScifi; i++){
318 std::string station = std::to_string(i+1);
319 fFeTargetX[i] = conf_floats[TString("Scifi/FeTargetX"+station)];
320 fFeTargetY[i] = conf_floats[TString("Scifi/FeTargetZ"+station)];
321 fFeTargetZ[i] = conf_floats[TString("Scifi/FeTargetY"+station)];
322 }
323
324 // DetID is of the form:
325 // first digit - station number
326 // second digit - type of the plane: 0-horizontal fiber, 1-vertical fiber
327 // third digit - mat number
328 // fourth digit - row number (in Z direction)
329 // last three digits - fiber number
330 // e.g. DetID = 1021074 -> station 1, horizontal fiber plane, mat 2, row 1, fiber 74
331 for (int istation = 0; istation < fNScifi; istation++){
332 Int_t node = 1e6*(istation+1);
333 std::string station = std::to_string(istation+1);
334 TGeoVolumeAssembly *ScifiVolume = new TGeoVolumeAssembly( TString("ScifiVolume"+station) );
335 TGeoVolumeAssembly *ScifiHorPlaneVol = new TGeoVolumeAssembly( TString("ScifiHorPlaneVol"+station) );
336 TGeoVolumeAssembly *ScifiVertPlaneVol = new TGeoVolumeAssembly( TString("ScifiVertPlaneVol"+station) );
337
338 //Adding the first half of the SciFi module that contains horizontal fibres
339 ScifiVolume->AddNode(CarbonFiberVolume, 0, new TGeoTranslation(0, 0, fZCarbonFiber/2));
340 ScifiVolume->AddNode(HoneycombVolume, 0, new TGeoTranslation(0, 0, fZCarbonFiber + fZHoneycomb/2));
341 ScifiVolume->AddNode(CarbonFiberVolume, 1, new TGeoTranslation(0, 0, fZCarbonFiber + fZHoneycomb + fZCarbonFiber/2));
342 ScifiVolume->AddNode(ScifiHorPlaneVol, node, new TGeoTranslation(0, 0, 2*fZCarbonFiber + fZHoneycomb + fZEpoxyMat/2));
343 ScifiVolume->AddNode(PlasticAirVolume, 0, new TGeoTranslation(0, 0, 2*fZCarbonFiber + fZHoneycomb + fZEpoxyMat+ fZPlastBar/2));
344
345 //Adding the second half of the SciFi module that contains vertical fibres
346 ScifiVolume->AddNode(PlasticAirVolume, 1, new TGeoCombiTrans("rottrans0", 0, 0, 2*fZCarbonFiber + fZHoneycomb + fZEpoxyMat + 3*fZPlastBar/2, rot));
347 ScifiVolume->AddNode(ScifiVertPlaneVol, node, new TGeoTranslation(0, 0, 2*fZCarbonFiber + fZHoneycomb + fZEpoxyMat + 2*fZPlastBar + fZEpoxyMat/2));
348 ScifiVolume->AddNode(CarbonFiberVolume, 2, new TGeoTranslation(0, 0, 2*fZCarbonFiber + fZHoneycomb + fZEpoxyMat + 2*fZPlastBar + fZEpoxyMat +fZCarbonFiber/2));
349 ScifiVolume->AddNode(HoneycombVolume, 1, new TGeoTranslation(0, 0, 3*fZCarbonFiber + fZHoneycomb + fZEpoxyMat + 2*fZPlastBar + fZEpoxyMat + fZHoneycomb/2));
350 ScifiVolume->AddNode(CarbonFiberVolume, 3, new TGeoTranslation(0, 0, 3*fZCarbonFiber + 2*fZHoneycomb + fZEpoxyMat + 2*fZPlastBar + fZEpoxyMat + fZCarbonFiber/2));
351
352 Double_t totalThickness = 4*fZCarbonFiber + 2*fZHoneycomb + 2*fZEpoxyMat + 2*fZPlastBar;
353
354 volTarget->AddNode(ScifiVolume, node,
355 new TGeoTranslation(DeltasV[istation][0], DeltasH[istation][1], DeltasH[istation][2]));
356
357 //std::cout<<"deltas "<<DeltasV[istation][0]<<" "<< DeltasH[istation][1]<<" "<< DeltasH[istation][2]<<" "<<totalThickness<<std::endl;
358 // for 2023 testbeam put iron blocks of variable length in between SciFi planes - the planes are dowstream of the blocks!
359 if (fNScifi==4 && istation != 0) {
360 volFeTarget[istation] = gGeoManager->MakeBox(TString("volFeTarget"+station),Fe,fFeTargetX[istation]/2., fFeTargetY[istation]/2., fFeTargetZ[istation]/2.);
361 volFeTarget[istation]->SetLineColor(kGreen-4);
362 volTarget->AddNode(volFeTarget[istation],1,
363 new TGeoTranslation(DeltasV[istation][0] ,
364 DeltasH[istation][1] ,
365 DeltasH[istation][2] - fFeTargetZ[istation]/2.));
366 }
367
368 //Creating Scifi planes by appending fiber mats
369 for (int imat = 0; imat < fNMats; imat++){
370 int N = fNMats==1 ? imat : imat-1;
371
372 //Placing mats along Y
373 ScifiHorPlaneVol->AddNode(HorMatVolume, 1e6*(istation+1) + 1e4*(imat + 1), new TGeoTranslation(0, N*(fWidthScifiMat+fGapScifiMat), 0));
374
375 //Placing mats along X
376 ScifiVertPlaneVol->AddNode(VertMatVolume, 1e6*(istation+1) + 1e5 + 1e4*(imat + 1), new TGeoTranslation(N*(fWidthScifiMat+fGapScifiMat), 0, 0));
377 }
378 }
379
380}
381
383{
384 if (gGeoManager->FindVolumeFast("SiPMmapVol")){return;}
385 Double_t fLengthScifiMat = conf_floats["Scifi/scifimat_length"];
386 Double_t fWidthChannel = conf_floats["Scifi/channel_width"];
387 Double_t fZEpoxyMat = conf_floats["Scifi/epoxymat_z"];
388 Int_t fNSiPMChan = conf_ints["Scifi/nsipm_channels"];
389 Int_t fNSiPMs = conf_ints["Scifi/nsipm_mat"];
390 Int_t fNMats = conf_ints["Scifi/nmats"];
391 Double_t fEdge = conf_floats["Scifi/sipm_edge"];
392 Double_t fCharr = conf_floats["Scifi/charr_width"];
393 Double_t fCharrGap = conf_floats["Scifi/charr_gap"];
394 Double_t fBigGap = conf_floats["Scifi/sipm_diegap"];
395 Double_t firstChannelX = conf_floats["Scifi/firstChannelX"];
396
397 //Contains all plane SiPMs, defined for horizontal fiber plane
398 //To obtain SiPM map for vertical fiber plane rotate by 90 degrees around Z
399 TGeoVolumeAssembly *SiPMmapVol = new TGeoVolumeAssembly("SiPMmapVol");
400
401 TGeoVolume*ChannelVol = gGeoManager->MakeBox("ChannelVol", 0, fLengthScifiMat/2, fWidthChannel/2, fZEpoxyMat/2);
402
403 //DetID for each channel:
404 //first digit: mat number (0-2)
405 //second digit: SiPM number (0-3)
406 //last three digits: channel number (0-127)
407
408 Double_t SiPMArray_fullwidth = fEdge+fCharr+fCharrGap+fCharr+fEdge;
409 TGeoVolumeAssembly *SiPMArrayVol;
410 int N = fNMats == 1 ? 1 : 0;
411 Double_t pos = -fEdge+firstChannelX + N*fLengthScifiMat;
412 for (int imat = 0; imat < fNMats; imat++){
413 for (int isipms = 0; isipms < fNSiPMs; isipms++){
414 pos+= fEdge;
415 for (int ichannel = 0; ichannel < fNSiPMChan; ichannel++){
416 SiPMmapVol->AddNode(ChannelVol, imat*10000+isipms *1000 + ichannel, new TGeoTranslation(0, pos, 0));
417 pos += fWidthChannel;
418 if (ichannel==(fNSiPMChan/2-1)){pos += fCharrGap;}
419 }
420 pos+=fEdge+fBigGap;
421 }
422 }
423}
424
426 // get mapping to eventHeader
427 eventHeader = e;
428
429 // Initialize
430 if (not alignment_init) {
431 alignment_init = true;
432 // Get available tags from the geometry file
433 std::string tag_string;
434
435 // Time alignment tags
436 for (auto key : conf_floats){
437 tag_string = key.first.Data();
438 if (tag_string.find("Scifi/station1t_") != std::string::npos){
439 covered_runs_time_alignment.push_back(stoi(tag_string.substr(tag_string.find("t_")+2)));
440 }
441 }
443 // Position alignment tags
444 for (auto key : conf_floats){
445 tag_string = key.first.Data();
446 if (tag_string.find("Scifi/LocM100t_") != std::string::npos){
447 covered_runs_position_alignment.push_back(stoi(tag_string.substr(tag_string.find("t_")+2)));
448 }
449 }
451 }
452};
453
454Bool_t Scifi::ProcessHits(FairVolume* vol)
455{
457 //Set parameters at entrance of volume. Reset ELoss.
458 if ( gMC->IsTrackEntering() )
459 {
460 fELoss = 0.;
461 fTime = gMC->TrackTime() * 1.0e09;
462 fLength = gMC->TrackLength();
463 gMC->TrackPosition(fPos);
464 gMC->TrackMomentum(fMom);
465 TGeoNavigator* nav = gGeoManager->GetCurrentNavigator();
466
467 int fibre_local_id = nav->GetMother()->GetNumber() - 1e6 - 1e4; // Local ID within the mat.
468 int fibre_mat_id = nav->GetMother(2)->GetNumber(); // Get mat ID.
469
470 int fibre_station_number = int( fibre_mat_id / 1e6); // Get the station number from the mat
471
472 int fibre_mat_id_station_removed = fibre_mat_id - fibre_station_number*1e6;
473 int fibre_mat_number = int((fibre_mat_id_station_removed - int(fibre_mat_id_station_removed/1e5)*1e5)/1e4);
474
475 fVolumeID = fibre_local_id + fibre_station_number*1e6 + fibre_mat_number*1e4;
476
477 if (fVolumeID==0){std::cout<<"fiber vol id "<<nav->GetMother()->GetName()<<std::endl;}
478
479 }
480 // Sum energy loss for all steps in the active volume
481 fELoss += gMC->Edep();
482
483 // Create ScifiPoint at exit of active volume
484 if ( gMC->IsTrackExiting() ||
485 gMC->IsTrackStop() ||
486 gMC->IsTrackDisappeared() ) {
487 if (fELoss == 0. ) { return kFALSE; }
488 fTrackID = gMC->GetStack()->GetCurrentTrackNumber();
489/* STMRFFF
490First digit S: station # within the sub-detector
491Second digit T: type of the plane: 0-horizontal fiber plane, 1-vertical fiber plane
492Third digit M: determines the mat number
493Fourth digit R: row number (in Z direction)
494Last three digits F: fiber number
495*/
496 TParticle* p=gMC->GetStack()->GetCurrentTrack();
497 Int_t pdgCode = p->GetPdgCode();
498
499 TLorentzVector Pos;
500 gMC->TrackPosition(Pos);
501 Double_t xmean = (fPos.X()+Pos.X())/2. ;
502 Double_t ymean = (fPos.Y()+Pos.Y())/2. ;
503 Double_t zmean = (fPos.Z()+Pos.Z())/2. ;
504
505 AddHit(fTrackID,fVolumeID, TVector3(xmean, ymean, zmean),
506 TVector3(fMom.Px(), fMom.Py(), fMom.Pz()), fTime, fLength,
507 fELoss, pdgCode);
508
509 // Increment number of det points in TParticle
510 ShipStack* stack = (ShipStack*) gMC->GetStack();
511 stack->AddPoint(kLHCScifi);
512 }
513
514 return kTRUE;
515}
516
517Double_t Scifi::GetCorrectedTime(Int_t fDetectorID, Double_t rawTime, Double_t L){
518/* expect time in u.ns and path length to sipm u.cm */
519 TString tag = "t";
520 TString sID;
521
522 if (eventHeader){
523 Int_t fRunNumber = eventHeader->GetRunId();
524 if (fRunNumber != last_run_time){
525 last_run_time = fRunNumber;
526 if (fRunNumber<1) {
527 LOG(ERROR) << "Scifi::GetCorrectedTime: non valid run number "<<fRunNumber;
528 return rawTime;
529 }
530
531 if (covered_runs_time_alignment.size()!=0){
532 tag = "t_"+std::to_string(covered_runs_time_alignment[covered_runs_time_alignment.size()-1]);
533 for (int i=1; i<covered_runs_time_alignment.size(); i++){
534 if (fRunNumber>=covered_runs_time_alignment[i-1] && fRunNumber<covered_runs_time_alignment[i]){
535 tag = "t_"+std::to_string(covered_runs_time_alignment[i-1]);
536 }
537 }
538 // special case
539 if (fRunNumber<5193 && fRunNumber>5174) tag = "t_"+std::to_string(covered_runs_time_alignment[0]);
540 }
541 else{
542 // allow reading older geo files with letter tags i.e. A, B, C
543 tag = "tA";
544 if (fRunNumber>5116 && !(fRunNumber<5193 && fRunNumber>5174) ) {tag = "tB";}
545 }
546 // 2023 testbeam data doesn't have a custom tag
547 if (fRunNumber>=1e5) {tag = "t";}
549 }
550 }
551 sID.Form("%i",fDetectorID);
552 Double_t cor = conf_floats["Scifi/station"+TString(sID(0,1))+last_time_alignment_tag];
553 if (sID(1,1)=="0"){
554 cor+=conf_floats["Scifi/station"+TString(sID(0,1))+"H"+TString(sID(2,1))+last_time_alignment_tag];
555 }else{
556 cor+=conf_floats["Scifi/station"+TString(sID(0,1))+"V"+TString(sID(2,1))+last_time_alignment_tag];
557 }
558 cor += L/conf_floats["Scifi/signalSpeed"];
559 return rawTime-cor;
560}
561
562void Scifi::GetPosition(Int_t fDetectorID, TVector3& A, TVector3& B)
563{
564// TGeoVolumeAssembly *SiPMmapVol = gGeoManager->FindVolumeFast("SiPMmapVol");
565// if(!SiPMmapVol ){SiPMmapVol=SiPMOverlap();}
566
567/* STMRFFF
568 First digit S: station # within the sub-detector
569 Second digit T: type of the plane: 0-horizontal fiber plane, 1-vertical fiber plane
570 Third digit M: determines the mat number
571 Fourth digit R: row number (in Z direction)
572 Last three digits F: fiber number
573*/
574
575 Int_t station_number = int(fDetectorID/1e6);
576 Int_t mat_number = int(fDetectorID/1e4)%int(fDetectorID/1e5);
577
578 Int_t local_fibre_id = fDetectorID - (station_number-1)*1e6 - (mat_number-1)*1e4;
579 TString sLocalID;
580 sLocalID.Form("%i", local_fibre_id);
581
582 TString sID;
583 sID.Form("%i",fDetectorID);
584 TString path = "/cave_1/Detector_0/volTarget_1/ScifiVolume"+TString(sID(0,1))+"_"+TString(sID(0,1))+"000000/";
585 if (sID(1,1)=="0"){
586 path+="ScifiHorPlaneVol"+TString(sID(0,1))+"_"+TString(sID(0,1))+"000000/";
587 path+="HorMatVolume_"+TString(sID(0,3))+"0000/";
588 }else{
589 path+="ScifiVertPlaneVol"+TString(sID(0,1))+"_"+TString(sID(0,1))+"000000/";
590 path+="VertMatVolume_"+TString(sID(0,3))+"0000/";
591 }
592 path+="FiberVolume_"+sLocalID;
593 TGeoNavigator* nav = gGeoManager->GetCurrentNavigator();
594 nav->cd(path);
595 LOG(DEBUG) <<path<<" "<<fDetectorID;
596 TGeoNode* W = nav->GetCurrentNode();
597 TGeoBBox* S = dynamic_cast<TGeoBBox*>(W->GetVolume()->GetShape());
598
599 Double_t top[3] = {0,0,S->GetDZ()};
600 Double_t bot[3] = {0,0,-(S->GetDZ())};
601 Double_t Gtop[3],Gbot[3];
602 nav->LocalToMaster(top, Gtop); nav->LocalToMaster(bot, Gbot);
603 A.SetXYZ(Gtop[0],Gtop[1],Gtop[2]);
604 B.SetXYZ(Gbot[0],Gbot[1],Gbot[2]);
605
606}
607TVector3 Scifi::GetLocalPos(Int_t id, TVector3* glob){
608 TString sID;
609 sID.Form("%i",id);
610 TString path = "/cave_1/Detector_0/volTarget_1/ScifiVolume"+TString(sID(0,1))+"_"+TString(sID(0,1))+"000000/";
611 if (sID(1,1)=="0"){
612 path+="ScifiHorPlaneVol"+TString(sID(0,1))+"_"+TString(sID(0,1))+"000000";
613 }else{
614 path+="ScifiVertPlaneVol"+TString(sID(0,1))+"_"+TString(sID(0,1))+"000000";
615 }
616 TGeoNavigator* nav = gGeoManager->GetCurrentNavigator();
617 nav->cd(path);
618 Double_t aglob[3];
619 Double_t aloc[3];
620 glob->GetXYZ(aglob);
621 nav->MasterToLocal(aglob,aloc);
622 return TVector3(aloc[0],aloc[1],aloc[2]);
623}
624
625void Scifi::GetSiPMPosition(Int_t SiPMChan, TVector3& A, TVector3& B)
626{
627/* STMRFFF
628 First digit S: station # within the sub-detector
629 Second digit T: type of the plane: 0-horizontal fiber plane, 1-vertical fiber plane
630 Third digit M: determines the mat number 0-2
631 Fourth digit S: SiPM number 0-3
632 Last three digits F: local SiPM channel number in one mat 0-127
633*/
634 Int_t locNumber = SiPMChan%100000;
635 Int_t globNumber = int(SiPMChan/100000)*100000;
636 Float_t locPosition = SiPMPos[locNumber]; // local position in plane of reference plane.
637 Double_t fFiberLength = conf_floats["Scifi/fiber_length"];
638 Int_t fNMats = conf_ints["Scifi/nmats"];
639
640 TString tag = "";
641
642 // in case of old data with FairEventHeader, user will be responsible to use the correct geofile.
643 if (eventHeader){
644 Int_t fRunNumber = eventHeader->GetRunId();
645 if (fRunNumber != last_run_pos){
646 last_run_pos = fRunNumber;
647
648 if (fRunNumber<1) {
649 LOG(ERROR) << "Scifi::GetSiPMPosition: non valid run number "<<fRunNumber;
650 return;
651 }
652
653 if (covered_runs_position_alignment.size()!=0){
654 tag = "t_"+std::to_string(covered_runs_position_alignment[covered_runs_position_alignment.size()-1]);
655 for (int i=1; i<covered_runs_position_alignment.size(); i++){
656 if (fRunNumber>=covered_runs_position_alignment[i-1] && fRunNumber<covered_runs_position_alignment[i]){
657 tag = "t_"+std::to_string(covered_runs_position_alignment[i-1]);
658 }
659 }
660 }
661 else{
662 // allow reading older geo files with letter tags i.e. A, B, C
663 tag = "E";
664 if (fRunNumber<4575) {tag = "A";}
665 else if (fRunNumber<4855) {tag = "B";}
666 else if (fRunNumber<5172) {tag = "C";}
667 else if (fRunNumber<5431) {tag = "D";}
668 }
669 // 2023 testbeam data doesn't have a custom tag
670 if (fRunNumber>=1e5) {tag = "";}
672 }
673 }
674 TString sID;
675 sID.Form("%i",SiPMChan);
676 Int_t digits = fNMats==1 ? 2 : 1;
677 locPosition += conf_floats["Scifi/LocM"+TString(sID(0,3))+last_position_alignment_tag];
678 Float_t rotPhi = conf_floats["Scifi/RotPhiS"+TString(sID(0,digits))+last_position_alignment_tag];
679 Float_t rotPsi = conf_floats["Scifi/RotPsiS"+TString(sID(0,digits))+last_position_alignment_tag];
680 Float_t rotTheta = conf_floats["Scifi/RotThetaS"+TString(sID(0,digits))+last_position_alignment_tag];
681
682 Double_t loc[3] = {0,0,0};
683 TString path = "/cave_1/Detector_0/volTarget_1/ScifiVolume"+TString(sID(0,1))+"_"+TString(sID(0,1))+"000000/";
684 TGeoNavigator* nav = gGeoManager->GetCurrentNavigator();
685 Double_t glob[3] = {0,0,0};
686
687 if (sID(1,1)=="0"){
688 path+="ScifiHorPlaneVol"+TString(sID(0,1))+"_"+TString(sID(0,1))+"000000";
689 loc[0] = -fFiberLength/2 - (rotPhi + rotPsi)*locPosition ;
690 loc[1] = locPosition - fFiberLength/2 * (rotPhi + rotPsi) ;
691 loc[2] = rotTheta*locPosition;
692 nav->cd(path);
693 nav->LocalToMaster(loc, glob);
694 A.SetXYZ( glob[0], glob[1],glob[2] );
695 loc[0] = fFiberLength/2 - (rotPhi + rotPsi)*locPosition ;
696 loc[1] = locPosition + fFiberLength/2 * (rotPhi + rotPsi) ;
697 loc[2] = - rotTheta*locPosition;
698 nav->LocalToMaster(loc, glob);
699 B.SetXYZ( glob[0], glob[1],glob[2] );
700 }else{
701 path+="ScifiVertPlaneVol"+TString(sID(0,1))+"_"+TString(sID(0,1))+"000000";
702 loc[0] = locPosition + fFiberLength/2*(rotPhi + rotPsi);
703 loc[1] = -fFiberLength/2 + locPosition*(rotPhi + rotPsi);
704 loc[2] = -fFiberLength/2*rotTheta;
705 nav->cd(path);
706 nav->LocalToMaster(loc, glob);
707 A.SetXYZ( glob[0], glob[1],glob[2] );
708 loc[0] = locPosition - fFiberLength/2*(rotPhi + rotPsi);
709 loc[1] = fFiberLength/2 + locPosition*(rotPhi + rotPsi);
710 loc[2] = -fFiberLength/2*rotTheta;
711 nav->LocalToMaster(loc, glob);
712 B.SetXYZ( glob[0], glob[1],glob[2] );
713 }
714}
715
716Double_t Scifi::ycross(Double_t a,Double_t R,Double_t x)
717{
718 Double_t y = -1;
719 Double_t A = R*R - (x-a)*(x-a);
720 if ( !(A<0) ){y = TMath::Sqrt(A);}
721 return y;
722}
723Double_t Scifi::integralSqrt(Double_t ynorm)
724{
725 Double_t y = 1./2.*(ynorm*TMath::Sqrt(1-ynorm*ynorm)+TMath::ASin(ynorm));
726 return y;
727}
728Double_t Scifi::fraction(Double_t R,Double_t x,Double_t y)
729{
730 Double_t F= 2*R*R*(integralSqrt(y/R) );
731 F-=(2*x*y);
732 Double_t result = F/(R*R*TMath::Pi());
733 return result;
734}
735Double_t Scifi::area(Double_t a,Double_t R,Double_t xL,Double_t xR)
736{
737 Double_t fracL = -1;
738 Double_t fracR = -1;
739 if (xL<=a-R && xR>=a+R) {return 1;}
740 Double_t leftC = ycross(a,R,xL);
741 Double_t rightC = ycross(a,R,xR);
742 if (leftC<0 && rightC<0) {return -1;}
743 if ( !(rightC<0) ){ fracR = fraction(R,abs(xR-a),rightC);}
744 if ( !(leftC<0) ) { fracL = fraction(R,abs(xL-a),leftC);}
745 Double_t theAnswer = 0;
746 if ( !(leftC<0) ) {
747 if(xL<a){theAnswer += 1-fracL;}
748 else{ theAnswer += fracL;}
749 if ( !(rightC<0) ) {theAnswer -=1;}
750 }
751 if ( !(rightC<0) ){
752 if(xR>a){ theAnswer += 1-fracR;}
753 else{ theAnswer += fracR;}
754 }
755 return theAnswer;
756}
757
759 Float_t fibresRadius = -1;
760 Float_t dSiPM = -1;
761 TGeoNode* vol;
762 TGeoNode* fibre;
763 SiPMOverlap(); // 12 SiPMs per mat, made for horizontal mats, fibres staggered along y-axis.
764 auto sipm = gGeoManager->FindVolumeFast("SiPMmapVol");
765 TObjArray* Nodes = sipm->GetNodes();
766 auto plane = gGeoManager->FindVolumeFast("ScifiHorPlaneVol1");
767 for (int imat = 0; imat < plane->GetNodes()->GetEntriesFast(); imat++){
768 auto mat = static_cast<TGeoNode*>(plane->GetNodes()->At(imat));
769 Float_t t1 = mat->GetMatrix()->GetTranslation()[1];
770 auto vmat = mat->GetVolume();
771 for (int ifibre = 0; ifibre < vmat->GetNodes()->GetEntriesFast(); ifibre++){
772 fibre = static_cast<TGeoNode*>(vmat->GetNodes()->At(ifibre));
773 if (fibresRadius<0){
774 auto tmp = fibre->GetVolume()->GetShape();
775 auto S = dynamic_cast<TGeoBBox*>(tmp);
776 fibresRadius = S->GetDX();
777 }
778 Float_t t2 = fibre->GetMatrix()->GetTranslation()[1];
779 Int_t fID = fibre->GetNumber()%100000 + imat*1e4; // local fibre number, global fibre number = SO+fID
780 Float_t a = t1+t2;
781
782 // check for overlap with any of the SiPM channels in the same mat
783 for(Int_t nChan = 0; nChan< Nodes->GetEntriesFast();nChan++){ // 12 SiPMs total and 4 SiPMs per mat times 128 channels
784 vol = static_cast<TGeoNode*>(Nodes->At(nChan));
785 Int_t N = vol->GetNumber()%100000;
786 if (imat!=int(N/10000)){continue;}
787 Float_t xcentre = vol->GetMatrix()->GetTranslation()[1];
788 if (dSiPM<0){
789 TGeoBBox* B = dynamic_cast<TGeoBBox*>(vol->GetVolume()->GetShape());
790 dSiPM = B->GetDY();
791 }
792 if (TMath::Abs(xcentre-a)>4*fibresRadius){ continue;} // no need to check further
793 Float_t W = area(a,fibresRadius,xcentre-dSiPM,xcentre+dSiPM);
794 if (W<0){ continue;}
795 std::array<float, 2> Wa;
796 Wa[0] = W;
797 Wa[1] = a;
798 fibresSiPM[N][fID] = Wa;
799 }
800 }
801 }
802 // calculate also local SiPM positions based on fibre positions and their fraction
803 // probably an overkill, maximum difference between weighted average and central position < 6 micron.
804 std::map<Int_t,std::map<Int_t,std::array<float, 2>>>::iterator it;
805 std::map<Int_t,std::array<float, 2>>::iterator itx;
806 for (it = fibresSiPM.begin(); it != fibresSiPM.end(); it++)
807 {
808 Int_t N = it->first;
809 Float_t m = 0;
810 Float_t w = 0;
811 for (itx = it->second.begin(); itx != it->second.end(); itx++)
812 {
813 m+=(itx->second)[0]*(itx->second)[1];
814 w+=(itx->second)[0];
815 }
816 SiPMPos[N]=m/w;
817 }
818// make inverse mapping, which fibre is associated to which SiPMs
819 for (it = fibresSiPM.begin(); it != fibresSiPM.end(); it++)
820 {
821 Int_t N = it->first;
822 for (itx = it->second.begin(); itx != it->second.end(); itx++)
823 {
824 Int_t nfibre = itx->first;
825 siPMFibres[nfibre][N]=itx->second;
826 }
827 }
828}
830{
831 fScifiPointCollection->Clear();
832}
833
834
836{
837
844 FairRootManager::Instance()->Register("ScifiPoint", "Scifi",
845 fScifiPointCollection, kTRUE);
846}
847
848TClonesArray* Scifi::GetCollection(Int_t iColl) const
849{
850 if (iColl == 0) { return fScifiPointCollection; }
851 else { return NULL; }
852}
853
855{
856 fScifiPointCollection->Clear();
857}
858
859
860ScifiPoint* Scifi::AddHit(Int_t trackID, Int_t detID,
861 TVector3 pos, TVector3 mom,
862 Double_t time, Double_t length,
863 Double_t eLoss, Int_t pdgCode)
864{
865 TClonesArray& clref = *fScifiPointCollection;
866 Int_t size = clref.GetEntriesFast();
867 return new(clref[size]) ScifiPoint(trackID, detID, pos, mom,
868 time, length, eLoss, pdgCode);
869}
870
Double_t m
@ kLHCScifi
Definition Scifi.h:20
TVector3 GetLocalPos(Int_t id, TVector3 *glob)
Definition Scifi.cxx:607
Double32_t fTime
momentum at entrance
Definition Scifi.h:109
std::map< Int_t, float > SiPMPos
inverse mapping
Definition Scifi.h:114
ScifiPoint * AddHit(Int_t trackID, Int_t detID, TVector3 pos, TVector3 mom, Double_t time, Double_t length, Double_t eLoss, Int_t pdgCode)
Definition Scifi.cxx:860
void GetSiPMPosition(Int_t SiPMChan, TVector3 &A, TVector3 &B)
Definition Scifi.cxx:625
Double32_t fELoss
length
Definition Scifi.h:111
TString last_time_alignment_tag
Definition Scifi.h:127
int last_run_time
Definition Scifi.h:126
virtual void EndOfEvent()
Definition Scifi.cxx:829
virtual void Register()
Definition Scifi.cxx:835
virtual TClonesArray * GetCollection(Int_t iColl) const
Definition Scifi.cxx:848
std::map< Int_t, std::map< Int_t, std::array< float, 2 > > > siPMFibres
mapping of fibres to SiPM channels
Definition Scifi.h:113
virtual Bool_t ProcessHits(FairVolume *v=0)
Definition Scifi.cxx:454
virtual void Reset()
Definition Scifi.cxx:854
std::vector< int > covered_runs_position_alignment
Definition Scifi.h:125
Scifi()
Definition Scifi.cxx:46
void GetPosition(Int_t id, TVector3 &vLeft, TVector3 &vRight)
Definition Scifi.cxx:562
bool alignment_init
Definition Scifi.h:129
std::map< TString, Int_t > conf_ints
Definition Scifi.h:119
std::map< TString, Float_t > conf_floats
Definition Scifi.h:118
void InitEvent(SNDLHCEventHeader *e)
Definition Scifi.cxx:425
TClonesArray * fScifiPointCollection
local SiPM channel position
Definition Scifi.h:116
Double_t ycross(Double_t a, Double_t R, Double_t x)
Definition Scifi.cxx:716
Double_t integralSqrt(Double_t ynorm)
Definition Scifi.cxx:723
int last_run_pos
Definition Scifi.h:126
virtual void Initialize()
Definition Scifi.cxx:92
std::map< Int_t, std::map< Int_t, std::array< float, 2 > > > fibresSiPM
energy loss
Definition Scifi.h:112
Double_t fraction(Double_t R, Double_t x, Double_t y)
Definition Scifi.cxx:728
virtual void SiPMOverlap()
Definition Scifi.cxx:382
Int_t InitMedium(const char *name)
Definition Scifi.cxx:98
std::vector< int > covered_runs_time_alignment
Definition Scifi.h:124
TString last_position_alignment_tag
Definition Scifi.h:128
TLorentzVector fPos
volume id
Definition Scifi.h:107
Double32_t fLength
time
Definition Scifi.h:110
void ConstructGeometry()
Definition Scifi.cxx:118
Double_t GetCorrectedTime(Int_t fDetectorID, Double_t rawTime, Double_t L)
Definition Scifi.cxx:517
virtual ~Scifi()
Definition Scifi.cxx:84
void SiPMmapping()
Definition Scifi.cxx:758
ClassDef(Scifi, 3) private Int_t fVolumeID
track index
Definition Scifi.h:98
TLorentzVector fMom
position at entrance
Definition Scifi.h:108
SNDLHCEventHeader * eventHeader
Definition Scifi.h:121
Double_t area(Double_t a, Double_t R, Double_t xL, Double_t xR)
Definition Scifi.cxx:735
ClassImp(ecalContFact) ecalContFact