Belle II Software  release-06-01-15
CDCSensitiveDetector.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <cdc/simulation/CDCSensitiveDetector.h>
10 
11 #include <cdc/simulation/CDCSimControlPar.h>
12 #include <cdc/simulation/Helix.h>
13 #include <cdc/geometry/CDCGeometryPar.h>
14 #include <cdc/utilities/ClosestApproach.h>
15 #include <framework/logging/Logger.h>
16 #include <framework/datastore/RelationArray.h>
17 
18 #include "G4Step.hh"
19 #include "G4TransportationManager.hh"
20 #include "G4Field.hh"
21 #include "G4FieldManager.hh"
22 
23 #include "CLHEP/Geometry/Vector3D.h"
24 #include "CLHEP/Geometry/Point3D.h"
25 
26 #include "TVector3.h"
27 
28 #ifndef ENABLE_BACKWARDS_COMPATIBILITY
30 #endif
31 #ifndef ENABLE_BACKWARDS_COMPATIBILITY
32 typedef HepGeom::Vector3D<double> HepVector3D;
33 #endif
34 
35 
36 
37 namespace Belle2 {
42  using namespace CDC;
43 
44  //N.B.#0: Do not put CDCGeometryPar::Instance() in the initializing list of the constructor,
45  //because it is called before CDCGeometryPar(geom) is called in case of UseDB=true of Geometry module.
46  //N.B.#1: Do not call AddNewDetector(), because it'll cause a job crash currently.
47 
48  CDCSensitiveDetector::CDCSensitiveDetector(G4String name, G4double thresholdEnergyDeposit, G4double thresholdKineticEnergy):
49  SensitiveDetectorBase(name, Const::CDC),
50  // m_cdcgp(CDCGeometryPar::Instance()),
51  m_cdcgp(nullptr),
52  m_thresholdEnergyDeposit(thresholdEnergyDeposit),
53  m_thresholdKineticEnergy(thresholdKineticEnergy), m_hitNumber(0)
54  {
56  registerMCParticleRelation(cdcSimHitRel);
57  // registerMCParticleRelation(cdcSimHitRel, RelationArray::c_doNothing);
58  // registerMCParticleRelation(cdcSimHitRel, RelationArray::c_negativeWeight);
59  // registerMCParticleRelation(cdcSimHitRel, RelationArray::c_deleteElement);
60  // registerMCParticleRelation(cdcSimHitRel, RelationArray::c_zeroWeight);
61  m_CDCSimHits.registerInDataStore();
63 
65 
67  m_thresholdEnergyDeposit *= CLHEP::GeV; //GeV to MeV (=unit in G4)
68  B2DEBUG(150, "CDCSensitiveDetector: Threshold energy (MeV): " << m_thresholdEnergyDeposit);
69  m_thresholdKineticEnergy = 0.0; // Dummy to avoid a warning (tentative).
70 
71  m_wireSag = cntlp.getWireSag();
72  // m_wireSag = false;
73  B2DEBUG(150, "CDCSensitiveDetector: Sense wire sag on(=1)/off(=0): " << m_wireSag);
74 
76  B2DEBUG(150, "CDCSensitiveDetector: Set left/right flag modified for tracking (=1)/ not set (=0): " << m_modifiedLeftRightFlag);
77 
79  m_minTrackLength *= CLHEP::cm; //cm to mm (=unit in G4)
80  B2DEBUG(150, "CDCSensitiveDetector: MinTrackLength (mm): " << m_minTrackLength);
81 
82  //For activating Initialize and EndOfEvent functions
83  //but not work --> commented out for a while...
84  // if (m_modifiedLeftRightFlag) {
85  // G4SDManager::GetSDMpointer()->AddNewDetector(this);
86  // }
87  }
88 
89  void CDCSensitiveDetector::Initialize(G4HCofThisEvent*)
90  {
91  /*
92  m_cdcgp = &CDCGeometryPar::Instance();
93 
94  m_thresholdEnergyDeposit = m_cdcgp->getThresholdEnergyDeposit();
95  m_thresholdEnergyDeposit *= CLHEP::GeV; //GeV to MeV (=unit in G4)
96  B2INFO("CDCSensitiveDetector: Threshold energy (MeV): " << m_thresholdEnergyDeposit);
97  m_modifiedLeftRightFlag = m_cdcgp->isModifiedLeftRightFlagOn();
98  B2INFO("CDCSensitiveDetector: Set left/right flag modified for tracking (=1)/ not set (=0): " << m_modifiedLeftRightFlag);
99 
100  m_minTrackLength = m_cdcgp->getMinTrackLength();
101  m_minTrackLength *= CLHEP::cm; //cm to mm (=unit in G4)
102  B2INFO("CDCSensitiveDetector: MinTrackLength (mm): " << m_minTrackLength);
103  */
104 
105  // Initialize
106  m_nonUniformField = 0;
107  // std::cout << "Initialize called" << std::endl;
108  // m_nPosHits = 0;
109  // m_nNegHits = 0;
110  }
111 
112  //-----------------------------------------------------
113  // Method invoked for every step in sensitive detector
114  //-----------------------------------------------------
115  bool CDCSensitiveDetector::step(G4Step* aStep, G4TouchableHistory*)
116  {
117  // static bool firstCall = true;
118  // if (firstCall) {
119  // firstCall = false;
121  // CDCSimControlPar & m_cntlp = CDCSimControlPar::getInstance();
122 
123  // // m_thresholdEnergyDeposit = m_cdcgp->getThresholdEnergyDeposit();
124  // m_thresholdEnergyDeposit = m_cntlp.getThresholdEnergyDeposit();
125  // m_thresholdEnergyDeposit *= CLHEP::GeV; //GeV to MeV (=unit in G4)
126  // B2INFO("CDCSensitiveDetector: Threshold energy (MeV): " << m_thresholdEnergyDeposit);
127 
128  // // m_modifiedLeftRightFlag = m_cdcgp->isModifiedLeftRightFlagOn();
129  // m_modifiedLeftRightFlag = m_cntlp.getModLeftRightFlag();
130  // B2INFO("CDCSensitiveDetector: Set left/right flag modified for tracking (=1)/ not set (=0): " << m_modifiedLeftRightFlag);
131 
132  // // m_minTrackLength = m_cdcgp->getMinTrackLength();
133  // m_minTrackLength = m_cntlp.getMinTrackLength();
134  // m_minTrackLength *= CLHEP::cm; //cm to mm (=unit in G4)
135  // B2INFO("CDCSensitiveDetector: MinTrackLength (mm): " << m_minTrackLength);
136 
137  // // m_wireSag = m_cdcgp->isWireSagOn();
138  // m_wireSag = m_cntlp.getWireSag();
139 
140  m_nonUniformField = 0;
141  // }
142 
143 #if defined(CDC_DEBUG)
144  std::cout << " " << std::endl;
145  std::cout << "********* step in ********" << std::endl;
146 #endif
147  // Get deposited energy
148  const G4double edep = aStep->GetTotalEnergyDeposit();
149 
150 
151  // Discard the hit below Edep_th
152  if (edep <= m_thresholdEnergyDeposit) return false;
153 
154  // Get step length
155  const G4double stepLength = aStep->GetStepLength();
156  if (stepLength == 0.) return false;
157 
158  // Get step information
159  const G4Track& t = * aStep->GetTrack();
160 
161  G4double hitWeight = Simulation::TrackInfo::getInfo(t).getIgnore() ? -1 : 1;
162  // save in MCParticle if track-length is enough long
163  if (t.GetTrackLength() > m_minTrackLength) {
164  Simulation::TrackInfo::getInfo(t).setIgnore(false);
165  hitWeight = 1.;
166  // std::cout <<"setignore=false for track= "<< t.GetTrackID() << std::endl;
167  // } else {
168  // std::cout <<"setignore=true for track= "<< t.GetTrackID() << std::endl;
169  }
170 
171  // const G4double tof = t.GetGlobalTime(); //tof at post step point
172  // if (isnan(tof)) {
173  // B2ERROR("SensitiveDetector: global time is nan");
174  // return false;
175  // }
176 
177  const G4int pid = t.GetDefinition()->GetPDGEncoding();
178  const G4double charge = t.GetDefinition()->GetPDGCharge();
179  const G4int trackID = t.GetTrackID();
180  // std::cout << "pid,stepl,trackID,trackl,weight= " << pid <<" "<< stepLength <<" "<< trackID <<" "<< t.GetTrackLength() <<" "<< hitWeight << std::endl;
181 
182  const G4VPhysicalVolume& v = * t.GetVolume();
183  const G4StepPoint& in = * aStep->GetPreStepPoint();
184  const G4StepPoint& out = * aStep->GetPostStepPoint();
185  const G4ThreeVector& posIn = in.GetPosition();
186  const G4ThreeVector& posOut = out.GetPosition();
187  const G4ThreeVector momIn(in.GetMomentum().x(), in.GetMomentum().y(),
188  in.GetMomentum().z());
189 #if defined(CDC_DEBUG)
190  std::cout << "pid = " << pid << std::endl;
191  std::cout << "mass = " << t.GetDefinition()->GetPDGMass() << std::endl;
192  std::cout << "posIn = " << posIn << std::endl;
193  std::cout << "posOut= " << posOut << std::endl;
194  std::cout << "tof at post-step = " << out.GetGlobalTime() << std::endl;
195  std::cout << "stepl = " << stepLength << std::endl;
196 #endif
197 
198  // Get layer ID
199  const unsigned layerId = v.GetCopyNo();
200  B2DEBUG(150, "LayerID in continuous counting method: " << layerId);
201 
202  // If neutral particles, ignore them, unless monopoles.
203 
204  if ((charge == 0.) && (abs(pid) != 99666)) return false;
205 
206  // Calculate cell ID
207  TVector3 tposIn(posIn.x() / CLHEP::cm, posIn.y() / CLHEP::cm, posIn.z() / CLHEP::cm);
208  TVector3 tposOut(posOut.x() / CLHEP::cm, posOut.y() / CLHEP::cm, posOut.z() / CLHEP::cm);
209  const unsigned idIn = m_cdcgp->cellId(layerId, tposIn);
210  const unsigned idOut = m_cdcgp->cellId(layerId, tposOut);
211 #if defined(CDC_DEBUG)
212  std::cout << "edep= " << edep << std::endl;
213  std::cout << "idIn,idOut= " << idIn << " " << idOut << std::endl;
214 #endif
215 
216  // Calculate drift length
217  std::vector<int> wires = WireId_in_hit_order(idIn, idOut, m_cdcgp->nWiresInLayer(layerId));
218  G4double sint(0.);
219  const G4double s_in_layer = stepLength / CLHEP::cm;
220  G4double xint[6] = {0};
221 
222  const G4ThreeVector momOut(out.GetMomentum().x(), out.GetMomentum().y(),
223  out.GetMomentum().z());
224  const G4double speedIn = in.GetVelocity();
225  const G4double speedOut = out.GetVelocity();
226  const G4double speed = 0.5 * (speedIn + speedOut);
227  const G4double speedInCmPerNs = speed / CLHEP::cm;
228 
229  const unsigned int nWires = wires.size();
230  G4double tofBefore = in.GetGlobalTime();
231  G4double kinEnergyBefore = in.GetKineticEnergy();
232  G4double momBefore = momIn.mag();
233  const G4double eLoss = kinEnergyBefore - out.GetKineticEnergy(); //n.b. not always equal to edep
234  const G4double mass = t.GetDefinition()->GetPDGMass();
235 #if defined(CDC_DEBUG)
236  std::cout << "momBefore = " << momBefore << std::endl;
237  std::cout << "momIn = " << momIn.x() << " " << momIn.y() << " " << momIn.z() << std::endl;
238  std::cout << "momOut= " << momOut.x() << " " << momOut.y() << " " << momOut.z() << std::endl;
239  std::cout << "speedIn,speedOut= " << speedIn << " " << speedOut << std::endl;
240  std::cout << " speedInCmPerNs= " << speedInCmPerNs << std::endl;
241  std::cout << "tofBefore= " << tofBefore << std::endl;
242 #endif
243 
244  const G4Field* field = G4TransportationManager::GetTransportationManager()->GetFieldManager()->GetDetectorField();
245 
246  for (unsigned i = 0; i < nWires; ++i) {
247 #if defined(CDC_DEBUG)
248  std::cout << "============ i,wires[i]= " << i << " " << wires[i] << std::endl;
249 #endif
250 
251  const G4double pos[3] = {posIn.x(), posIn.y(), posIn.z()};
252  G4double Bfield[3];
253  field->GetFieldValue(pos, Bfield);
254  m_magneticField = (Bfield[0] == 0. && Bfield[1] == 0. &&
255  Bfield[2] == 0.) ? false : true;
256 #if defined(CDC_DEBUG)
257  std::cout << "Bfield= " << Bfield[0] << " " << Bfield[1] << " " << Bfield[2] << std::endl;
258  std::cout << "magneticField= " << m_magneticField << std::endl;
259 #endif
260 
261  double distance = 0;
262  G4ThreeVector posW(0, 0, 0);
263  HepPoint3D onTrack;
264  HepPoint3D pOnTrack;
265 
266  // Calculate forward/backward position of current wire
267  const TVector3 tfw3v = m_cdcgp->wireForwardPosition(layerId, wires[i]);
268  const TVector3 tbw3v = m_cdcgp->wireBackwardPosition(layerId, wires[i]);
269 
270  const HepPoint3D fwd(tfw3v.x(), tfw3v.y(), tfw3v.z());
271  const HepPoint3D bck(tbw3v.x(), tbw3v.y(), tbw3v.z());
272 
273  if (m_magneticField && (abs(pid) != 99666)) {
274  // For monopoles a line segment approximation in the step volume is done,
275  // which is more reasonable, but should be done with a proper catenary FIXME
276  // Cal. distance assuming helix track (still approximation)
277  m_nonUniformField = 1;
278  if (Bfield[0] == 0. && Bfield[1] == 0. &&
279  Bfield[2] != 0.) m_nonUniformField = 0;
280 
281  const G4double B_kG[3] = {Bfield[0] / CLHEP::kilogauss,
282  Bfield[1] / CLHEP::kilogauss,
283  Bfield[2] / CLHEP::kilogauss
284  };
285 #if defined(CDC_DEBUG)
286  std::cout << "B_kG= " << B_kG[0] << " " << B_kG[1] << " " << B_kG[2] << std::endl;
287  std::cout << "magneticField= " << m_magneticField << std::endl;
288 #endif
289 
290  const HepPoint3D x(pos[0] / CLHEP::cm, pos[1] / CLHEP::cm, pos[2] / CLHEP::cm);
291  const HepVector3D p(momIn.x() / CLHEP::GeV, momIn.y() / CLHEP::GeV, momIn.z() / CLHEP::GeV);
292  Helix tmp(x, p, charge);
293  tmp.bFieldZ(B_kG[2]);
294  tmp.ignoreErrorMatrix();
295 
296  /* // Calculate forward/backward position of current wire
297  const TVector3 tfw3v = cdcg.wireForwardPosition(layerId, wires[i]);
298  const TVector3 tbw3v = cdcg.wireBackwardPosition(layerId, wires[i]);
299 
300  const HepPoint3D fwd(tfw3v.x(), tfw3v.y(), tfw3v.z());
301  const HepPoint3D bck(tbw3v.x(), tbw3v.y(), tbw3v.z());
302  */
303 
304  const HepVector3D wire = fwd - bck;
305  HepPoint3D tryp =
306  (x.z() - bck.z()) / wire.z() * wire + bck;
307  tmp.pivot(tryp);
308  tryp = (tmp.x(0.).z() - bck.z()) / wire.z() * wire + bck;
309  tmp.pivot(tryp);
310  tryp = (tmp.x(0.).z() - bck.z()) / wire.z() * wire + bck;
311  tmp.pivot(tryp);
312 
313  distance = std::abs(tmp.a()[0]);
314  posW.setX(tryp.x());
315  posW.setY(tryp.y());
316  posW.setZ(tryp.z());
317 
318  // HepPoint3D onTrack = tmp.x(0.);
319  onTrack = tmp.x(0.);
320  pOnTrack = tmp.momentum(0.);
321 
322  for_Rotat(B_kG);
323  const G4double xwb(bck.x()), ywb(bck.y()), zwb(bck.z());
324  const G4double xwf(fwd.x()), ywf(fwd.y()), zwf(fwd.z());
325  const G4double xp(onTrack.x()), yp(onTrack.y()), zp(onTrack.z());
326  const G4double px(pOnTrack.x()), py(pOnTrack.y()), pz(pOnTrack.z());
327  G4double q2[3] = {0.}, q1[3] = {0.}, q3[3] = {0.};
328  const G4int ntryMax(50); //tentative; too large probably...
329  G4double dist;
330  G4int ntry(999);
331  HELWIR(xwb, ywb, zwb, xwf, ywf, zwf,
332  xp, yp, zp, px, py, pz,
333  B_kG, charge, ntryMax, dist, q2, q1, q3, ntry);
334 
335 #if defined(CDC_DEBUG)
336  std::cout << "ntry= " << ntry << std::endl;
337  std::cout << "bf distance= " << distance << std::endl;
338  std::cout << "onTrack = " << onTrack << std::endl;
339  std::cout << "posW = " << posW << std::endl;
340 #endif
341  if (ntry <= ntryMax) {
342  if (m_wireSag) {
343  G4double ywb_sag, ywf_sag;
344  m_cdcgp->getWireSagEffect(CDCGeometryPar::c_Base, layerId, wires[i], q2[2], ywb_sag, ywf_sag);
345  HELWIR(xwb, ywb_sag, zwb, xwf, ywf_sag, zwf,
346  xp, yp, zp, px, py, pz,
347  B_kG, charge, ntryMax, dist, q2, q1, q3, ntry);
348  }
349  if (ntry <= ntryMax) {
350  distance = dist;
351  onTrack.setX(q1[0]);
352  onTrack.setY(q1[1]);
353  onTrack.setZ(q1[2]);
354  posW.setX(q2[0]);
355  posW.setY(q2[1]);
356  posW.setZ(q2[2]);
357  pOnTrack.setX(q3[0]);
358  pOnTrack.setY(q3[1]);
359  pOnTrack.setZ(q3[2]);
360  }
361 #if defined(CDC_DEBUG)
362  std::cout << " " << std::endl;
363  std::cout << "helix distance= " << distance << std::endl;
364  std::cout << "onTrack = " << onTrack << std::endl;
365  std::cout << "posW = " << posW << std::endl;
366  std::cout << "pOnTrack= " << pOnTrack << std::endl;
367  G4ThreeVector bwp(bck.x(), bck.y(), bck.z());
368  G4ThreeVector fwp(fwd.x(), fwd.y(), fwd.z());
369  G4ThreeVector hitPosition, wirePosition;
370  distance = ClosestApproach(bwp, fwp, posIn / CLHEP::cm, posOut / CLHEP::cm,
371  hitPosition, wirePosition);
372  if (m_wireSag) {
373  G4double ywb_sag, ywf_sag;
374  m_cdcgp->getWireSagEffect(CDCGeometryPar::c_Base, layerId, wires[i], wirePosition.z(), ywb_sag, ywf_sag);
375  bwp.setY(ywb_sag);
376  fwp.setY(ywf_sag);
377  distance = ClosestApproach(bwp, fwp, posIn / CLHEP::cm, posOut / CLHEP::cm,
378  hitPosition, wirePosition);
379  }
380  std::cout << "line distance= " << distance << std::endl;
381  std::cout << "onTrack= " << hitPosition.x() << " " << hitPosition.y() << " " << hitPosition.z() << std::endl;
382  std::cout << "posW = " << wirePosition.x() << " " << wirePosition.y() << " " << wirePosition.z() << std::endl;
383 #endif
384  }
385  } else { //no magnetic field case
386  // Cal. distance assuming a line track
387  G4ThreeVector bwp(bck.x(), bck.y(), bck.z());
388  G4ThreeVector fwp(fwd.x(), fwd.y(), fwd.z());
389  G4ThreeVector hitPosition, wirePosition;
390  distance = ClosestApproach(bwp, fwp, posIn / CLHEP::cm, posOut / CLHEP::cm,
391  hitPosition, wirePosition);
392  if (m_wireSag) {
393  G4double ywb_sag, ywf_sag;
394  m_cdcgp->getWireSagEffect(CDCGeometryPar::c_Base, layerId, wires[i], wirePosition.z(), ywb_sag, ywf_sag);
395  bwp.setY(ywb_sag);
396  fwp.setY(ywf_sag);
397  distance = ClosestApproach(bwp, fwp, posIn / CLHEP::cm, posOut / CLHEP::cm,
398  hitPosition, wirePosition);
399  }
400 
401  onTrack.setX(hitPosition.x());
402  onTrack.setY(hitPosition.y());
403  onTrack.setZ(hitPosition.z());
404  posW.setX(wirePosition.x());
405  posW.setY(wirePosition.y());
406  posW.setZ(wirePosition.z());
407  //tentative setting
408  pOnTrack.setX(0.5 * (momIn.x() + momOut.x()) / CLHEP::GeV);
409  pOnTrack.setY(0.5 * (momIn.y() + momOut.y()) / CLHEP::GeV);
410  pOnTrack.setZ(0.5 * (momIn.z() + momOut.z()) / CLHEP::GeV);
411  } //end of magneticfiled on or off
412 
413 #if defined(CDC_DEBUG)
414  std::cout << "af distance= " << distance << std::endl;
415  std::cout << "onTrack = " << onTrack << std::endl;
416  std::cout << "posW = " << posW << std::endl;
417  std::cout << "pOnTrack = " << pOnTrack << std::endl;
418  if (distance > 2.4) {
419  std::cout << "toolargedriftl" << std::endl;
420  }
421 #endif
422  distance *= CLHEP::cm; onTrack *= CLHEP::cm; posW *= CLHEP::cm;
423  pOnTrack *= CLHEP::GeV;
424 
425  G4ThreeVector posTrack(onTrack.x(), onTrack.y(), onTrack.z());
426  G4ThreeVector mom(pOnTrack.x(), pOnTrack.y(), pOnTrack.z());
427 
428  const TVector3 tPosW(posW.x(), posW.y(), posW.z());
429  const TVector3 tPosTrack(posTrack.x(), posTrack.y(), posTrack.z());
430  const TVector3 tMom(mom.x(), mom.y(), mom.z());
431  G4int lr = m_cdcgp->getOldLeftRight(tPosW, tPosTrack, tMom);
432  G4int newLrRaw = m_cdcgp->getNewLeftRightRaw(tPosW, tPosTrack, tMom);
433  // if(abs(pid) == 11) {
434  // std::cout <<"pid,lr,newLrRaw 4electron= " << pid <<" "<< lr <<" "<< newLrRaw << std::endl;
435  // }
436  G4int newLr = newLrRaw; //to be modified in EndOfEvent
437 
438  if (nWires == 1) {
439 
440  // saveSimHit(layerId, wires[i], trackID, pid, distance, tofBefore, edep, s_in_layer * cm, momIn, posW, posIn, posOut, posTrack, lr, newLrRaw, newLr, speed);
441  saveSimHit(layerId, wires[i], trackID, pid, distance, tofBefore, edep, s_in_layer * CLHEP::cm, pOnTrack, posW, posIn, posOut,
442  posTrack, lr, newLrRaw, newLr, speed, hitWeight);
443 #if defined(CDC_DEBUG)
444  std::cout << "saveSimHit" << std::endl;
445  std::cout << "momIn = " << momIn << std::endl;
446  std::cout << "pOnTrack = " << pOnTrack << std::endl;
447 #endif
448 
449  } else {
450 
451  G4int cel1 = wires[i] + 1;
452  G4int cel2 = cel1;
453  if (i + 1 <= nWires - 1) {
454  cel2 = wires[i + 1] + 1;
455  }
456  const G4double s2 = t.GetTrackLength() / CLHEP::cm; //at post-step
457  G4double s1 = (s2 - s_in_layer); //at pre-step; varied later
458  G4ThreeVector din = momIn;
459  if (din.mag() != 0.) din /= momIn.mag();
460 
461  G4double vent[6] = {posIn.x() / CLHEP::cm, posIn.y() / CLHEP::cm, posIn.z() / CLHEP::cm, din.x(), din.y(), din.z()};
462 
463  G4ThreeVector dot(momOut.x(), momOut.y(), momOut.z());
464  if (dot.mag() != 0.) {
465  dot /= dot.mag();
466  } else {
467  // Flight-direction is needed to set even when a particle stops
468  dot = din;
469  }
470 
471  G4double vext[6] = {posOut.x() / CLHEP::cm, posOut.y() / CLHEP::cm, posOut.z() / CLHEP::cm, dot.x(), dot.y(), dot.z()};
472 
473  if (i > 0) {
474  for (int j = 0; j < 6; ++j) vent[j] = xint[j];
475  s1 = sint;
476  }
477 
478  // const G4int ic(3); // cubic approximation of the track
479  G4int flag(0);
480  G4double edep_in_cell(0.);
481  G4double eLossInCell(0.);
482 
483  if (cel1 != cel2) {
484 #if defined(CDC_DEBUG)
485  std::cout << "layerId,cel1,cel2= " << layerId << " " << cel1 << " " << cel2 << std::endl;
486  std::cout << "vent= " << vent[0] << " " << vent[1] << " " << vent[2] << " " << vent[3] << " " << vent[4] << " " << vent[5] <<
487  std::endl;
488  std::cout << "vext= " << vext[0] << " " << vext[1] << " " << vext[2] << " " << vext[3] << " " << vext[4] << " " << vext[5] <<
489  std::endl;
490  std::cout << "s1,s2,ic= " << s1 << " " << s2 << " " << ic << std::endl;
491 #endif
492  CellBound(layerId, cel1, cel2, vent, vext, s1, s2, xint, sint, flag);
493 #if defined(CDC_DEBUG)
494  std::cout << "flag,sint= " << flag << " " << sint << std::endl;
495  std::cout << "xint= " << xint[0] << " " << xint[1] << " " << xint[2] << " " << xint[3] << " " << xint[4] << " " << xint[5] <<
496  std::endl;
497 #endif
498 
499  const G4double test = (sint - s1) / s_in_layer;
500  if (test < 0. || test > 1.) {
501  B2WARNING("CDCSensitiveDetector: Strange path length: " << "s1= " << s1 << " sint= " << sint << " s_in_layer= " << s_in_layer <<
502  " test= " << test);
503  }
504  edep_in_cell = edep * std::abs((sint - s1)) / s_in_layer;
505 
506  const G4ThreeVector x_In(vent[0]*CLHEP::cm, vent[1]*CLHEP::cm, vent[2]*CLHEP::cm);
507  const G4ThreeVector x_Out(xint[0]*CLHEP::cm, xint[1]*CLHEP::cm, xint[2]*CLHEP::cm);
508  const G4ThreeVector p_In(momBefore * vent[3], momBefore * vent[4], momBefore * vent[5]);
509 
510  // saveSimHit(layerId, wires[i], trackID, pid, distance, tofBefore, edep_in_cell, (sint - s1) * cm, p_In, posW, x_In, x_Out, posTrack, lr, newLrRaw, newLr, speed);
511  saveSimHit(layerId, wires[i], trackID, pid, distance, tofBefore, edep_in_cell, std::abs((sint - s1)) * CLHEP::cm, pOnTrack, posW,
512  x_In, x_Out,
513  posTrack, lr, newLrRaw, newLr, speed, hitWeight);
514 #if defined(CDC_DEBUG)
515  std::cout << "saveSimHit" << std::endl;
516  std::cout << "p_In = " << p_In << std::endl;
517  std::cout << "pOnTrack= " << pOnTrack << std::endl;
518 #endif
519  tofBefore += (sint - s1) / speedInCmPerNs;
520  eLossInCell = eLoss * (sint - s1) / s_in_layer;
521  kinEnergyBefore -= eLossInCell;
522  if (kinEnergyBefore >= 0.) {
523  momBefore = sqrt(kinEnergyBefore * (kinEnergyBefore + 2.*mass));
524  } else {
525  B2WARNING("CDCSensitiveDetector: Kinetic Energy < 0.");
526  momBefore = 0.;
527  }
528 
529  } else { //the particle exits
530 
531  const G4double test = (s2 - sint) / s_in_layer;
532  if (test < 0. || test > 1.) {
533  B2WARNING("CDCSensitiveDetector: Strange path length: " << "s2= " << s2 << " sint= " << sint << " s_in_layer= " << s_in_layer <<
534  " test= " << test);
535  }
536  edep_in_cell = edep * std::abs((s2 - sint)) / s_in_layer;
537 
538  const G4ThreeVector x_In(vent[0]*CLHEP::cm, vent[1]*CLHEP::cm, vent[2]*CLHEP::cm);
539  const G4ThreeVector p_In(momBefore * vent[3], momBefore * vent[4], momBefore * vent[5]);
540 
541  // saveSimHit(layerId, wires[i], trackID, pid, distance, tofBefore, edep_in_cell, (s2 - sint) * cm, p_In, posW, x_In, posOut, posTrack, lr, newLrRaw, newLr, speed);
542  saveSimHit(layerId, wires[i], trackID, pid, distance, tofBefore, edep_in_cell, std::abs((s2 - sint)) * CLHEP::cm, pOnTrack, posW,
543  x_In,
544  posOut, posTrack, lr, newLrRaw, newLr, speed, hitWeight);
545 #if defined(CDC_DEBUG)
546  std::cout << "saveSimHit" << std::endl;
547  std::cout << "p_In = " << p_In << std::endl;
548  std::cout << "pOnTrack= " << pOnTrack << std::endl;
549 #endif
550  }
551  }
552  //setSeenInDetectorFlag(aStep, MCParticle::c_SeenInCDC);
553 
557  //StoreArray<Relation> mcPartToSimHits(getRelationCollectionName());
558  //StoreArray<MCParticle> mcPartArray(DEFAULT_MCPARTICLES);
559  //if (saveIndex < 0) {B2FATAL("SimHit wasn't saved despite charge != 0");}
560  //StoreArray<CDCSimHit> m_CDCSimHits(DEFAULT_CDCSIMHITS);
561 
562  //new(mcPartToSimHits->AddrAt(saveIndex)) Relation(mcPartArray, m_CDCSimHits, trackID, saveIndex);
563 
564  } //end of wire loop
565 
566  return true;
567  }
568 
569  /*
570  void CDCSensitiveDetector::BeginOfEvent(G4HCofThisEvent*)
571  {
572  std::cout <<"CDCSensitiveDetector::BeginOfEvent callded." << std::endl;
573  }
574  */
575 
576  void CDCSensitiveDetector::EndOfEvent(G4HCofThisEvent*)
577  {
579  }
580 
581  void
582  CDCSensitiveDetector::saveSimHit(const G4int layerId,
583  const G4int wireId,
584  const G4int trackID,
585  const G4int pid,
586  const G4double distance,
587  const G4double tof,
588  const G4double edep,
589  const G4double stepLength,
590  const G4ThreeVector& mom,
591  const G4ThreeVector& posW,
592  const G4ThreeVector& posIn,
593  const G4ThreeVector& posOut,
594  const G4ThreeVector& posTrack,
595  const G4int lr,
596  const G4int newLrRaw,
597  const G4int newLr,
598  const G4double speed,
599  const G4double hitWeight)
600  {
601 
602  // Discard the hit below Edep_th
603  // if (edep <= m_thresholdEnergyDeposit) return 0;
604  if (edep <= m_thresholdEnergyDeposit) return;
605 
606  //compute tof at the closest point; linear approx.
607  const G4double sign = (posTrack - posIn).dot(mom) < 0. ? -1. : 1.;
608  const G4double CorrectTof = tof + sign * (posTrack - posIn).mag() / speed;
609  // if (sign < 0.) std::cout <<"deltatof= "<< sign * (posTrack - posIn).mag() / speed << std::endl;
610 #if defined(CDC_DEBUG)
611  std::cout << "posIn= " << posIn.x() << " " << posIn.y() << " " << posIn.z() << std::endl;
612  std::cout << "posOut= " << posOut.x() << " " << posOut.y() << " " << posOut.z() << std::endl;
613  std::cout << "posTrack= " << posTrack.x() << " " << posTrack.y() << " " << posTrack.z() << std::endl;
614  std::cout << "posW= " << posW.x() << " " << posW.y() << " " << posW.z() << std::endl;
615  std::cout << "tof = " << tof << std::endl;
616  std::cout << "deltaTof = " << (posTrack - posIn).mag() / speed << std::endl;
617  std::cout << "CorrectTof= " << CorrectTof << std::endl;
618  if (CorrectTof > 95) {
619  std::cout << "toolargecorrecttof" << std::endl;
620  }
621 #endif
622 
624 
625  m_hitNumber = m_CDCSimHits.getEntries();
626 
627  CDCSimHit* simHit = m_CDCSimHits.appendNew();
628 
629  simHit->setWireID(layerId, wireId);
630  simHit->setTrackId(trackID);
631  simHit->setPDGCode(pid);
632  simHit->setDriftLength(distance / CLHEP::cm);
633  simHit->setFlightTime(CorrectTof / CLHEP::ns);
634  simHit->setGlobalTime(CorrectTof / CLHEP::ns);
635  simHit->setEnergyDep(edep / CLHEP::GeV);
636  simHit->setStepLength(stepLength / CLHEP::cm);
637  TVector3 momentum(mom.getX() / CLHEP::GeV, mom.getY() / CLHEP::GeV, mom.getZ() / CLHEP::GeV);
638  simHit->setMomentum(momentum);
639  TVector3 posWire(posW.getX() / CLHEP::cm, posW.getY() / CLHEP::cm, posW.getZ() / CLHEP::cm);
640  simHit->setPosWire(posWire);
641  TVector3 positionIn(posIn.getX() / CLHEP::cm, posIn.getY() / CLHEP::cm, posIn.getZ() / CLHEP::cm);
642  simHit->setPosIn(positionIn);
643  TVector3 positionOut(posOut.getX() / CLHEP::cm, posOut.getY() / CLHEP::cm, posOut.getZ() / CLHEP::cm);
644  simHit->setPosOut(positionOut);
645  TVector3 positionTrack(posTrack.getX() / CLHEP::cm, posTrack.getY() / CLHEP::cm, posTrack.getZ() / CLHEP::cm);
646  simHit->setPosTrack(positionTrack);
647  simHit->setPosFlag(lr);
648  simHit->setLeftRightPassageRaw(newLrRaw);
649  simHit->setLeftRightPassage(newLr);
650 #if defined(CDC_DEBUG)
651  std::cout << "sensitived,oldlr,newlrRaw,newlr= " << lr << " " << newLrRaw << " " << newLr << std::endl;
652 #endif
653 
654  B2DEBUG(150, "HitNumber: " << m_hitNumber);
656  //N.B. Negative hitWeight is allowed intentionally here; all weights are to be reset to positive in EndOfEvent
657  cdcSimHitRel.add(trackID, m_hitNumber, hitWeight);
658  } else {
659  cdcSimHitRel.add(trackID, m_hitNumber);
660  }
661 
662  // if (hitWeight > 0) m_nPosHits++;
663  // if (hitWeight < 0) m_nNegHits++;
664  // std::cout <<"trackID,HitNumber,weight,driftL,edep= "<< trackID <<" "<< m_hitNumber <<" "<< hitWeight <<" "<< distance <<" "<< edep << std::endl;
665  // return (m_hitNumber);
666  }
667 
668 
669  /*
670  void SensitiveDetector::AddbgOne(bool doit) {
671  Belle::Datcdc_olhit_Manager& olhitmgr=Belle::Datcdc_olhit_Manager::get_manager();
672  if(doit) {
673  for( int i=0;i<olhitmgr.count();i++ ){
674  Belle::Datcdc_olhit& h = olhitmgr[i];
675  }
676  dout(Debugout::B2INFO,"SensitiveDetector")
677  << "AddbgOne " << olhitmgr.size()
678  << std::endl;
679  }
680  olhitmgr.remove();
681  }
682  */
683 
684  void
685  CDCSensitiveDetector::CellBound(const G4int layerId,
686  const G4int ic1,
687  const G4int ic2,
688  const G4double venter[6],
689  const G4double vexit[6],
690  const G4double s1, const G4double s2,
691  G4double xint[6],
692  G4double& sint, G4int& iflag)
693  {
694  //---------------------------------------------------------------------------
695  // (Purpose)
696  // calculate an intersection of track with cell boundary.
697  //
698  // (Relations)
699  // Calls GCUBS
700  //
701  // (Arguments)
702  // input
703  // ic1 serial cell# (start w/ one) of entrance.
704  // ic2 serial cell# (start w/ one) of exit.
705  // venter(6) (x,y,z,px/p,py/p,pz/p) at entrance.
706  // vexit(6) (x,y,z,px/p,py/p,pz/p) at exit.
707  // s1 track length at entrance.
708  // s2 track length at exit.
709  // output
710  // xint(6) (x,y,z,px/p,py/p,pz/p) at intersection of cell boundary.
711  // sint track length at intersection of cell boundary.
712  // iflag return code.
713  //
714  // N.B.(TODO ?) CDC misalignment wrt Belle2 coordinate system is ignored
715  // when calculating the cell-boundary assuming misalign. is small.
716  //--------------------------------------------------------------------------
717 
718  G4double div = m_cdcgp->nWiresInLayer(layerId);
719 
720  //Check if s1, s2, ic1 and ic2 are ok
721  if (s1 >= s2) {
722  B2ERROR("CDCSensitiveDetector: s1(=" << s1 << ") > s2(=" << s2 << ")");
723  }
724  if (std::abs(ic1 - ic2) != 1) {
725  if (ic1 == 1 && ic2 == div) {
726  } else if (ic1 == div && ic2 == 1) {
727  } else {
728  B2ERROR("CDCSensitiveDetector: |ic1 - ic2| != 1 in CellBound; " << "ic1=" << ic1 << " " << "ic2=" << ic2);
729  }
730  }
731 
732  //get wire positions for the entrance cell
733  G4double xwb = (m_cdcgp->wireBackwardPosition(layerId, ic1 - 1)).x();
734  G4double ywb = (m_cdcgp->wireBackwardPosition(layerId, ic1 - 1)).y();
735  G4double zwb = (m_cdcgp->wireBackwardPosition(layerId, ic1 - 1)).z();
736  G4double xwf = (m_cdcgp->wireForwardPosition(layerId, ic1 - 1)).x();
737  G4double ywf = (m_cdcgp->wireForwardPosition(layerId, ic1 - 1)).y();
738  G4double zwf = (m_cdcgp->wireForwardPosition(layerId, ic1 - 1)).z();
739 
740  /*
741  G4double pathl = sqrt((vexit[0] - venter[0]) * (vexit[0] - venter[0])
742  + (vexit[1] - venter[1]) * (vexit[1] - venter[1])
743  + (vexit[2] - venter[2]) * (vexit[2] - venter[2]));
744  std::cout << "app pathl= " << pathl << std::endl;
745  G4double dot = venter[3] * vexit[3] + venter[4] * vexit[4];
746  dot /= sqrt(venter[3] * venter[3] + venter[4] * venter[4]);
747  dot /= sqrt( vexit[3] * vexit[3] + vexit[4] * vexit[4]);
748  if (dot < 0.) std::cout <<"negativedot= " << dot << std::endl;
749  */
750 
751  //copy arrays
752  G4double xx1[6], xx2[6];
753  for (int i = 0; i < 6; ++i) {
754  xx1[i] = venter[i];
755  xx2[i] = vexit [i];
756  }
757 
758  //calculate the field wire position betw. cell#1 and #2
759  G4double psi = double(ic2 - ic1) * CLHEP::pi / div;
760  if (ic1 == 1 && ic2 == div) {
761  psi = -CLHEP::pi / div;
762  } else if (ic1 == div && ic2 == 1) {
763  psi = CLHEP::pi / div;
764  }
765  G4double cospsi = cos(psi);
766  G4double sinpsi = sin(psi);
767 
768  G4double xfwb = cospsi * xwb - sinpsi * ywb;
769  G4double yfwb = sinpsi * xwb + cospsi * ywb;
770  G4double xfwf = cospsi * xwf - sinpsi * ywf;
771  G4double yfwf = sinpsi * xwf + cospsi * ywf;
772  G4double zfwb = zwb;
773  G4double zfwf = zwf;
774 
775  //prepare quantities related to the cell-boundary
776  G4double vx = xfwf - xfwb;
777  G4double vy = yfwf - yfwb;
778  G4double vz = zfwf - zfwb;
779  G4double vv = sqrt(vx * vx + vy * vy + vz * vz);
780  vx /= vv; vy /= vv; vz /= vv;
781 
782  //translate to make the cubic description easier
783  G4double shiftx = (xx1[0] + xx2[0]) * 0.5;
784  G4double shifty = (xx1[1] + xx2[1]) * 0.5;
785  G4double shiftz = (xx1[2] + xx2[2]) * 0.5;
786  G4double shifts = (s1 + s2) * 0.5;
787  G4double xshft = xx1[0] - shiftx;
788  G4double yshft = xx1[1] - shifty;
789  G4double zshft = xx1[2] - shiftz;
790  G4double sshft = s1 - shifts;
791 
792  //approximate the trajectroy by cubic curves
793  G4double pabs1 = sqrt(xx1[3] * xx1[3] + xx1[4] * xx1[4] + xx1[5] * xx1[5]);
794  G4double pabs2 = sqrt(xx2[3] * xx2[3] + xx2[4] * xx2[4] + xx2[5] * xx2[5]);
795  // std::cout << "pabs1,2= " << pabs1 <<" "<< pabs2 << std::endl;
796 
797  G4double a[4] = {0.}, b[4] = {0.}, c[4] = {0.};
798 
799  if (m_magneticField) {
800  GCUBS(sshft, xshft, xx1[3] / pabs1, xx2[3] / pabs2, a);
801  GCUBS(sshft, yshft, xx1[4] / pabs1, xx2[4] / pabs2, b);
802  GCUBS(sshft, zshft, xx1[5] / pabs1, xx2[5] / pabs2, c);
803  // std::cout <<"a= " << a[0] <<" "<< a[1] <<" "<< a[2] <<" "<< a[3] << std::endl;
804  // std::cout <<"b= " << b[0] <<" "<< b[1] <<" "<< b[2] <<" "<< b[3] << std::endl;
805  // std::cout <<"c= " << c[0] <<" "<< c[1] <<" "<< c[2] <<" "<< c[3] << std::endl;
806  } else {
807  //n.b. following is really better ?
808  a[1] = xshft / sshft;
809  b[1] = yshft / sshft;
810  c[1] = zshft / sshft;
811  }
812 
813  //calculate an int. point betw. the trajectory and the cell-boundary
814  G4double stry(0.), xtry(0.), ytry(0.), ztry(0.);
815  G4double beta(0.), xfw(0.), yfw(0.);
816  G4double sphi(0.), cphi(0.), dphil(0.), dphih(0.);
817  const G4int maxTrials = 100;
818  const G4double eps = 5.e-4;
819  G4double sl = sshft; // negative value
820  G4double sh = -sshft; // positive value
821  G4int i = 0;
822 
823  //set initial value (dphil) for the 1st iteration
824  stry = sl;
825  xtry = shiftx + a[0] + stry * (a[1] + stry * (a[2] + stry * a[3]));
826  ytry = shifty + b[0] + stry * (b[1] + stry * (b[2] + stry * b[3]));
827  ztry = shiftz + c[0] + stry * (c[1] + stry * (c[2] + stry * c[3]));
828  beta = (ztry - zfwb) / vz;
829  xfw = xfwb + beta * vx;
830  yfw = yfwb + beta * vy;
831  sphi = (xtry * yfw - ytry * xfw);
832  cphi = (xtry * xfw + ytry * yfw);
833  dphil = atan2(sphi, cphi); //n.b. no need to conv. to dphi...
834 
835  iflag = 1;
836 
837  while (((sh - sl) > eps) && (i < maxTrials)) {
838  stry = 0.5 * (sl + sh);
839  xtry = shiftx + a[0] + stry * (a[1] + stry * (a[2] + stry * a[3]));
840  ytry = shifty + b[0] + stry * (b[1] + stry * (b[2] + stry * b[3]));
841  ztry = shiftz + c[0] + stry * (c[1] + stry * (c[2] + stry * c[3]));
842  beta = (ztry - zfwb) / vz;
843  xfw = xfwb + beta * vx;
844  yfw = yfwb + beta * vy;
845 
846  sphi = (xtry * yfw - ytry * xfw);
847  cphi = (xtry * xfw + ytry * yfw);
848  dphih = atan2(sphi, cphi); //n.b. no need to conv. to dphi...
849 
850  if (dphil * dphih > 0.) {
851  sl = stry;
852  } else {
853  sh = stry;
854  }
855  ++i;
856  }
857 
858  // std::cout << "itry= " << i << std::endl;
859  if (i >= maxTrials - 1) {
860  iflag = 0;
861  B2WARNING("CDCSensitiveDetector: No intersection ?");
862 
863  /* G4double ds = 1.e-4;
864  G4int imax = (s2 - s1) / ds + 1;
865  G4double rdphimin = DBL_MAX;
866 
867  for (i=0; i <= imax; ++i) {
868  stry = sshft + i * ds;
869  xtry = shiftx + a[0] + stry * (a[1] + stry * (a[2] + stry * a[3]));
870  ytry = shifty + b[0] + stry * (b[1] + stry * (b[2] + stry * b[3]));
871  ztry = shiftz + c[0] + stry * (c[1] + stry * (c[2] + stry * c[3]));
872  beta = (ztry - zfwb) / vz;
873  xfw = xfwb + beta * vx;
874  yfw = yfwb + beta * vy;
875 
876  sphi = (xtry * yfw - ytry * xfw);
877  cphi = (xtry * xfw + ytry * yfw);
878  dphi = atan2(sphi, cphi);
879  rdphi = sqrt(xfw * xfw + yfw * yfw) * dphi;
880 
881  if ( std::abs(rdphi) < std::abs(rdphimin)) {
882  rdphimin = rdphi;
883  imin = i;
884  }
885  }
886  */
887  }
888  // sint = sshft + imin * ds;
889  sint = stry;
890 
891  // std::cout <<"i,dphil,dphih,sint= " << i <<" "<< dphil <<" "<< dphih <<" "<< sint << std::endl;
892  //get the trajectory at the int. point
893  xint[0] = a[0] + sint * (a[1] + sint * (a[2] + sint * a[3]));
894  xint[1] = b[0] + sint * (b[1] + sint * (b[2] + sint * b[3]));
895  xint[2] = c[0] + sint * (c[1] + sint * (c[2] + sint * c[3]));
896  xint[3] = a[1] + sint * (2. * a[2] + 3. * sint * a[3]);
897  xint[4] = b[1] + sint * (2. * b[2] + 3. * sint * b[3]);
898  xint[5] = c[1] + sint * (2. * c[2] + 3. * sint * c[3]);
899 
900  //translate back to the lab. frame
901  xint[0] += shiftx;
902  xint[1] += shifty;
903  xint[2] += shiftz;
904  sint += shifts;
905  /*
906  std::cout <<"s1,s2,sint= " << s1 <<" "<< s2 <<" "<< sint << std::endl;
907  std::cout <<" xx1= " << xx1[0] <<" "<< xx1[1] <<" "<< xx1[2] << std::endl;
908  std::cout <<" xx2= " << xx2[0] <<" "<< xx2[1] <<" "<< xx2[2] << std::endl;
909  std::cout <<"xint= " << xint[0] <<" "<< xint[1] <<" "<< xint[2] << std::endl;
910  */
911 
912  /* if (((xx1[0] <= xint[0] && xint[0] <= xx2[0]) ||
913  (xx2[0] <= xint[0] && xint[0] <= xx1[0])) &&
914  ((xx1[1] <= xint[1] && xint[1] <= xx2[1]) ||
915  (xx2[1] <= xint[1] && xint[1] <= xx1[1])) &&
916  ((xx1[2] <= xint[2] && xint[2] <= xx2[2]) ||
917  (xx2[2] <= xint[2] && xint[2] <= xx1[2])) &&
918  (s1 <= sint && sint <= s2)) {
919  } else {
920  std::cout << "strangeinttersection" << std::endl;
921  }
922  */
923  //re-normalize to one since abs=1 is not guearanteed in the cubic approx.
924  G4double p = sqrt(xint[3] * xint[3] + xint[4] * xint[4] + xint[5] * xint[5]);
925  xint[3] /= p; xint[4] /= p; xint[5] /= p;
926  // std::cout << "norm= " << p << std::endl;
927  // std::cout <<"s1,s2,sint= " << s1 <<" "<< s2 <<" "<< sint << std::endl;
928  // std::cout <<"xint= " << xint[0] <<" "<< xint[1] <<" "<< xint[2] << std::endl;
929  // std::cout <<"xint= " << xint[3] <<" "<< xint[4] <<" "<< xint[5] << std::endl;
930  }
931 
932  void CDCSensitiveDetector::GCUBS(const G4double x, const G4double y, const G4double d1, const G4double d2, G4double a[4])
933  {
934  //Original: GCUBS in Geant3
935  // ******************************************************************
936  // * *
937  // * Calculates a cubic through P1,(X,Y),(-X,-Y),P2 *
938  // * Y=A(1)+A(2)*X+A(3)*X**2+A(4)*X**3 *
939  // * The coordinate system is assumed to be the cms system *
940  // * of P1,P2. *
941  // * d1(2): directional cosine at P1(2). *
942  // * *
943  // * ==>Called by : GIPLAN,GICYL *
944  // * Author H.Boerner ********* *
945  // * *
946  // ******************************************************************
947 
948  G4double fact(0);
949 
950  if (x == 0.) goto L10;
951 
952  fact = (d1 - d2) * 0.25;
953  a[0] = - 1. * fact * x;
954  a[2] = fact / x;
955  a[1] = (6. * y - (d1 + d2) * x) / (4. * x);
956  a[3] = ((d1 + d2) * x - 2.*y) / (4.*x * x * x);
957  return;
958 
959 L10:
960  a[0] = 0.;
961  a[1] = 1.;
962  a[2] = 0.;
963  a[3] = 0.;
964  }
965 
966  void
967  CDCSensitiveDetector::for_Rotat(const G4double bfld[3])
968  {
969  //Calculates a rotation matrix in advance at a local position in lab.
970  //The rotation is done about the coord. origin; lab.-frame to B-field
971  //frame in which only Bz-comp. is non-zero.
972  //~dead copy of gsim_cdc_for_rotat.F in gsim-cdc for Belle (for tentaive use)
973 
974  if (m_nonUniformField == 0) return;
975 
976  G4double bx, by, bz;
977  bx = bfld[0];
978  by = bfld[1];
979  bz = bfld[2];
980 
981  //cal. rotation matrix
982  G4double bxz, bfield;
983  bxz = bx * bx + bz * bz;
984  bfield = bxz + by * by;
985  bxz = sqrt(bxz);
986  bfield = sqrt(bfield);
987 
988  m_brot[0][0] = bz / bxz;
989  m_brot[1][0] = 0.;
990  m_brot[2][0] = -bx / bxz;
991  m_brot[0][1] = -by * bx / bxz / bfield;
992  m_brot[1][1] = bxz / bfield;
993  m_brot[2][1] = -by * bz / bxz / bfield;
994  m_brot[0][2] = bx / bfield;
995  m_brot[1][2] = by / bfield;
996  m_brot[2][2] = bz / bfield;
997 
998  return;
999 
1000  }
1001 
1002  void
1003  CDCSensitiveDetector::Rotat(G4double& x, G4double& y, G4double& z,
1004  const int mode)
1005  {
1006  //Translates (x,y,z) in lab. to (x,y,z) in B-field frame (mode=1), or reverse
1007  // translation (mode=-1).
1008  //~dead copy (for tentaive use) of gsim_cdc_rotat/irotat.F in gsim-cdc
1009  //for Belle
1010 
1011  if (m_nonUniformField == 0) return;
1012 
1013  G4double x0(x), y0(y), z0(z);
1014 
1015  if (mode == 1) {
1016  x = m_brot[0][0] * x0 + m_brot[1][0] * y0 + m_brot[2][0] * z0;
1017  y = m_brot[0][1] * x0 + m_brot[1][1] * y0 + m_brot[2][1] * z0;
1018  z = m_brot[0][2] * x0 + m_brot[1][2] * y0 + m_brot[2][2] * z0;
1019  } else if (mode == -1) {
1020  x = m_brot[0][0] * x0 + m_brot[0][1] * y0 + m_brot[0][2] * z0;
1021  y = m_brot[1][0] * x0 + m_brot[1][1] * y0 + m_brot[1][2] * z0;
1022  z = m_brot[2][0] * x0 + m_brot[2][1] * y0 + m_brot[2][2] * z0;
1023  } else {
1024  //B2ERROR("SensitiveDetector " <<"invalid mode " << mode << "specifed");
1025  }
1026  return;
1027 
1028  }
1029 
1030  void
1031  CDCSensitiveDetector::Rotat(G4double x[3], const int mode)
1032  {
1033  //Translates (x,y,z) in lab. to (x,y,z) in B-field frame (mode=1), or reverse
1034  // translation (mode=-1).
1035  //~dead copy (for tentaive use) of gsim_cdc_rotat/irotat.F in gsim-cdc
1036  //for Belle
1037 
1038  if (m_nonUniformField == 0) return;
1039 
1040  G4double x0(x[0]), y0(x[1]), z0(x[2]);
1041 
1042  if (mode == 1) {
1043  x[0] = m_brot[0][0] * x0 + m_brot[1][0] * y0 + m_brot[2][0] * z0;
1044  x[1] = m_brot[0][1] * x0 + m_brot[1][1] * y0 + m_brot[2][1] * z0;
1045  x[2] = m_brot[0][2] * x0 + m_brot[1][2] * y0 + m_brot[2][2] * z0;
1046  } else if (mode == -1) {
1047  x[0] = m_brot[0][0] * x0 + m_brot[0][1] * y0 + m_brot[0][2] * z0;
1048  x[1] = m_brot[1][0] * x0 + m_brot[1][1] * y0 + m_brot[1][2] * z0;
1049  x[2] = m_brot[2][0] * x0 + m_brot[2][1] * y0 + m_brot[2][2] * z0;
1050  } else {
1051  //B2ERROR("SensitiveDetector " <<"invalid mode " << mode << "specifed");
1052  }
1053  return;
1054 
1055  }
1056 
1057  void
1058  CDCSensitiveDetector::HELWIR(const G4double xwb4, const G4double ywb4,
1059  const G4double zwb4,
1060  const G4double xwf4, const G4double ywf4,
1061  const G4double zwf4,
1062  const G4double xp, const G4double yp,
1063  const G4double zp,
1064  const G4double px, const G4double py,
1065  const G4double pz,
1066  const G4double B_kG[3],
1067  const G4double charge, const G4int ntryMax,
1068  G4double& distance,
1069  G4double q2[3], G4double q1[3],
1070  G4double q3[3],
1071  G4int& ntry)
1072  {
1073  //~dead copy of gsim_cdc_hit.F in gsim-cdc for Belle (for tentaive use)
1074  // ---------------------------------------------------------------------
1075  // Purpose : Calculate closest points between helix and wire.
1076  //
1077  // Input
1078  // xwb4 : x of wire at backward endplate in lab.
1079  // ywb4 : y of wire at backward endplate "
1080  // zwb4 : z of wire at backward endplate "
1081  // xwf4 : x of wire at forward endplate "
1082  // ywf4 : y of wire at forward endplate "
1083  // zwf4 : z of wire at forward endplate "
1084  //
1085  // Output
1086  // q2(1) : x of wire at closest point in lab.
1087  // q2(2) : y of wire at closest point "
1088  // q2(3) : z of wire at closest point "
1089  // q1(1) : x of helix at closest point "
1090  // q1(2) : y of helix at closest point "
1091  // q1(3) : z of helix at closest point "
1092  // ntry :
1093  // ---------------------------------------------------------------------
1094 
1095  const G4int ndim = 3;
1096  const G4double delta = 1.e-5;
1097 
1098 
1099  G4double xwb, ywb, zwb, xwf, ywf, zwf;
1100  G4double xw, yw, zw, xh, yh, zh, pxh, pyh, pzh;
1101  G4double fi, fi_corr;
1102 
1103  G4double dr, fi0, cpa, dz, tanl;
1104  G4double x0, y0, z0;
1105  // "chrg" removed by M. U. June, 2nd, 2013
1106  // G4double xc, yc, r, chrg;
1107  G4double xc, yc, r;
1108  G4double xwm, ywm;
1109  G4double sinfi0, cosfi0, sinfi0fi, cosfi0fi;
1110 
1111  G4double vx, vy, vz, vv, cx, cy, cz, tt[3][3];
1112  G4double tmp[3];
1113 
1114  G4double xx[3], dxx[3], ddxx[3], pp[3];
1115  G4double xxtdxx, dxxtdxx, xxtddxx;
1116 
1117 
1118  G4double fst = 0.0;
1119  G4double f, fderiv, deltafi, fact, eval;
1120  G4double dx1, dy1, dx2, dy2, crs, dot;
1121 
1122  G4int iflg;
1123 
1124  //set parameters
1125  xwb = xwb4; ywb = ywb4; zwb = zwb4;
1126  xwf = xwf4; ywf = ywf4; zwf = zwf4;
1127 
1128  G4double xxx(xp), yyy(yp), zzz(zp);
1129  G4double pxx(px), pyy(py), pzz(pz);
1130 
1131  //rotate z-axis to be parallel to B-field in case of non-uniform B
1132  Rotat(xwb, ywb, zwb, 1);
1133  Rotat(xwf, ywf, zwf, 1);
1134  Rotat(xxx, yyy, zzz, 1);
1135  Rotat(pxx, pyy, pzz, 1);
1136 
1137  G4double a[8] = {0.};
1138  G4double pt = sqrt(pxx * pxx + pyy * pyy);
1139  a[1] = atan2(-pxx, pyy);
1140  a[2] = charge / pt;
1141  a[4] = pzz / pt;
1142  a[5] = xxx; a[6] = yyy; a[7] = zzz;
1143 
1144  //calculate unit direction vector of the sense wire
1145  vx = xwf - xwb; vy = ywf - ywb; vz = zwf - zwb;
1146  vv = sqrt(vx * vx + vy * vy + vz * vz);
1147  vx /= vv; vy /= vv; vz /= vv;
1148 
1149  //flag for distingushing between stereo and axial wire
1150  iflg = 0;
1151  if (vx == 0. && vy == 0.) iflg = 1;
1152  // std::cout << "iflg= " << iflg << std::endl;
1153  //write(6,*) ' hlx2wir ', xwb, ywb, zwb, vx, vy, vz
1154 
1155  //calculate coefficients of f
1156  cx = xwb - vx * (vx * xwb + vy * ywb + vz * zwb);
1157  cy = ywb - vy * (vx * xwb + vy * ywb + vz * zwb);
1158  cz = zwb - vz * (vx * xwb + vy * ywb + vz * zwb);
1159 
1160  //calculate tensor for f
1161  tt[0][0] = vx * vx - 1.; tt[1][0] = vx * vy; tt[2][0] = vx * vz;
1162  tt[0][1] = vy * vx; tt[1][1] = vy * vy - 1.; tt[2][1] = vy * vz;
1163  tt[0][2] = vz * vx; tt[1][2] = vz * vy; tt[2][2] = vz * vz - 1.;
1164 
1165  //set helix parameters
1166  dr = a[0]; fi0 = a[1]; cpa = a[2];
1167  dz = a[3]; tanl = a[4];
1168  x0 = a[5]; y0 = a[6]; z0 = a[7];
1169 
1170  //
1171  // set initial value for phi
1172  //
1173 
1174  xwm = xxx;
1175  ywm = yyy;
1176  //r(cm) = alpha/cpa = alpha * pt(GeV); bfield(kG)
1177  G4double bfield = sqrt(B_kG[0] * B_kG[0] +
1178  B_kG[1] * B_kG[1] +
1179  B_kG[2] * B_kG[2]);
1180  G4double alpha = 1.e4 / 2.99792458 / bfield;
1181  r = alpha / cpa;
1182  cosfi0 = cos(fi0);
1183  sinfi0 = sin(fi0);
1184  xc = x0 + (dr + r) * cosfi0;
1185  yc = y0 + (dr + r) * sinfi0;
1186  dx1 = x0 - xc;
1187  dy1 = y0 - yc;
1188  dx2 = xwm - xc;
1189  dy2 = ywm - yc;
1190  crs = dx1 * dy2 - dy1 * dx2;
1191  dot = dx1 * dx2 + dy1 * dy2;
1192  fi = atan2(crs, dot);
1193 
1194  //begin iterative procedure for newton 's method '
1195  fact = 1.;
1196  ntry = 0;
1197 line1:
1198  ntry += 1;
1199  cosfi0fi = cos(fi0 + fi);
1200  sinfi0fi = sin(fi0 + fi);
1201 
1202  //calculate spatial point Q(x,y,z) along the helix
1203  xx[0] = x0 + dr * cosfi0 + r * (cosfi0 - cosfi0fi);
1204  xx[1] = y0 + dr * sinfi0 + r * (sinfi0 - sinfi0fi);
1205  xx[2] = z0 + dz - r * tanl * fi;
1206  pp[0] = -pt * sinfi0fi;
1207  pp[1] = pt * cosfi0fi;
1208  pp[2] = pt * tanl;
1209 
1210  if (iflg == 1) {
1211  q2[0] = xwb; q2[1] = ywb; q2[2] = xx[2];
1212  q1[0] = xx[0]; q1[1] = xx[1]; q1[2] = xx[2];
1213  q3[0] = pp[0]; q3[1] = pp[1]; q3[2] = pp[2];
1214  //inverse rotation to lab. frame in case of non-uniform B
1215  Rotat(q1, -1);
1216  Rotat(q2, -1);
1217  Rotat(q3, -1);
1218  distance = sqrt((q2[0] - q1[0]) * (q2[0] - q1[0]) +
1219  (q2[1] - q1[1]) * (q2[1] - q1[1]) +
1220  (q2[2] - q1[2]) * (q2[2] - q1[2]));
1221  return;
1222  }
1223 
1224  //calculate direction vector (dx/dphi,dy/dphi,dz/dphi)
1225  //on a point along the helix.
1226  dxx[0] = r * sinfi0fi; dxx[1] = - r * cosfi0fi; dxx[2] = - r * tanl;
1227 
1228  // In order to derive the closest pont between straight line and helix,
1229  // we can put following two conditions:
1230  // (i) A point H(xh,yh,zh) on the helix given should be on
1231  // the plane which is perpendicular to the straight line.
1232  // (ii) A line HW from W(xw,yw,zw) which is a point on the straight
1233  // line to H(xh,yh,zh) should normal to the direction vector
1234  // on the point H.
1235  //
1236  // Thus, we can make a equation from above conditions.
1237  // f(phi) = cx*(dx/dphi) + cy*(dy/dphi) + cz*(dz/dphi)
1238  // + (x,y,z)*tt(i,j)*(dx/dphi,dy/dphi,dz/dphi)
1239  // = 0,
1240  // where
1241  // cx = xwb - vx*( vx*xwb + vy*ywb + vz*zwb )
1242  // cy = ywb - vy*( vx*xwb + vy*ywb + vz*zwb )
1243  // cz = zwb - vz*( vx*xwb + vy*ywb + vz*zwb )
1244  //
1245  // tt(1,1) = vx*vx - 1 tt(1,2) = vx*vy tt(1,3) = vx*vz
1246  // tt(2,1) = vy*vx tt(2,2) = vy*vy - 1 tt(2,3) = vy*vz
1247  // tt(3,1) = vz*vx tt(3,2) = vz*vy tt(3,3) = vz*vz - 1
1248  //
1249  // and the equation of straight line(stereo wire) is written by
1250  // (x,y,z) = (xwb,ywb,zwb) + beta*(vx,vy,vz), beta is free parameter.
1251 
1252  //Now calculate f
1253  Mvopr(ndim, xx, tt, dxx, tmp, 1);
1254  xxtdxx = tmp[0];
1255  f = cx * dxx[0] + cy * dxx[1] + cz * dxx[2] + xxtdxx;
1256  if (std::abs(f) < delta) goto line100;
1257 
1258  //evaluate fitting result and prepare some factor to multiply to 1/derivative
1259  if (ntry > 1) {
1260  eval = (1.0 - 0.25 * fact) * std::abs(fst) - std::abs(f);
1261  if (eval <= 0.) fact *= 0.5;
1262  }
1263 
1264  //calculate derivative of f
1265  ddxx[0] = r * cosfi0fi; ddxx[1] = r * sinfi0fi; ddxx[2] = 0.;
1266 
1267  //Now we have derivative of f
1268  Mvopr(ndim, dxx, tt, dxx, tmp, 1);
1269  dxxtdxx = tmp[0];
1270  Mvopr(ndim, xx, tt, ddxx, tmp, 1);
1271  xxtddxx = tmp[0];
1272  fderiv = cx * ddxx[0] + cy * ddxx[1] + cz * ddxx[2] + dxxtdxx + xxtddxx;
1273  // Commented by M. U. June, 2nd, 2013
1274  // fist = fi;
1275  deltafi = f / fderiv;
1276  fi -= fact * deltafi;
1277  fst = f;
1278 
1279  if (ntry > ntryMax) {
1280  //B2DEBUG(" Exceed max. trials HelWir ");
1281  goto line100;
1282  }
1283  //write(6,*) ntry, fist, deltafi
1284  goto line1;
1285 
1286  //check if zh is btw zwb and zwf; if not, set zh=zwb or zh=zwf.
1287  //dead regions due to feed-throughs should be considered later.
1288 line100:
1289  zh = z0 + dz - r * tanl * fi;
1290  fi_corr = 0.;
1291  if (zh < zwb) fi_corr = (zwb - zh) / (-r * tanl);
1292  if (zh > zwf) fi_corr = (zwf - zh) / (-r * tanl);
1293  fi += fi_corr;
1294 
1295  cosfi0fi = cos(fi0 + fi);
1296  sinfi0fi = sin(fi0 + fi);
1297 
1298  xh = x0 + dr * cosfi0 + r * (cosfi0 - cosfi0fi);
1299  yh = y0 + dr * sinfi0 + r * (sinfi0 - sinfi0fi);
1300  zh = z0 + dz - r * tanl * fi;
1301  pxh = -pt * sinfi0fi;
1302  pyh = pt * cosfi0fi;
1303  pzh = pt * tanl;
1304 
1305  //write(6,*) 'fi_corr, zh, zwb, zwf=', fi_corr, zh, zwb, zwf
1306  //write(6,*) 'zh = ', z0, dz, r, tanl, fi
1307 
1308  zw = vx * vz * xh + vy * vz * yh + vz * vz * zh + zwb - vz * (vx * xwb + vy * ywb + vz * zwb);
1309  xw = xwb + vx * (zw - zwb) / vz;
1310  yw = ywb + vy * (zw - zwb) / vz;
1311 
1312  q2[0] = xw; q2[1] = yw; q2[2] = zw;
1313  q1[0] = xh; q1[1] = yh; q1[2] = zh;
1314  q3[0] = pxh; q3[1] = pyh; q3[2] = pzh;
1315 
1316  //inverse rotation to lab. frame in case of non-uniform B
1317  Rotat(q1, -1);
1318  Rotat(q2, -1);
1319  Rotat(q3, -1);
1320  distance = sqrt((q2[0] - q1[0]) * (q2[0] - q1[0]) +
1321  (q2[1] - q1[1]) * (q2[1] - q1[1]) +
1322  (q2[2] - q1[2]) * (q2[2] - q1[2]));
1323  return;
1324 
1325  }
1326 
1327  void
1328  CDCSensitiveDetector::Mvopr(const G4int ndim, const G4double b[3], const G4double m[3][3],
1329  const G4double a[3], G4double c[3], const G4int mode)
1330  {
1331  //~dead copy of UtilCDC_mvopr in com-cdc for Belle (for tentative use)
1332  //-----------------------------------------------------------------------
1333  // Input
1334  // ndim : dimension
1335  // b(1-ndim) : vector
1336  // m(1-ndim,1-ndim) : matrix
1337  // a(1-ndim) : vector
1338  // c(1-ndim) : vector
1339  // mode : c = m * a for mode=0
1340  // c = b * m * a for mode=1
1341  // Output
1342  // c(1-ndim) : for mode 1, solution is put on c[0]
1343  //-----------------------------------------------------------------------
1344 
1345  if (ndim != 3) {
1346  //B2ERROR("invalid ndim " << ndim << " specified");
1347  return;
1348  }
1349 
1350  for (int i = 0; i < ndim; ++i) c[i] = 0.;
1351  G4double tmp[3];
1352  for (int i = 0; i < ndim; ++i) tmp[i] = 0.;
1353 
1354  if (mode == 0) {
1355  for (int i = 0; i < ndim; ++i) {
1356  for (int j = 0; j < ndim; ++j) {
1357  c[i] += m[j][i] * a[j];
1358  }
1359  }
1360  return;
1361  } else if (mode == 1) {
1362  for (int i = 0; i < ndim; ++i) {
1363  for (int j = 0; j < ndim; ++j) {
1364  tmp[i] += m[j][i] * a[j];
1365  }
1366  c[0] += b[i] * tmp[i];
1367  }
1368  } else {
1369  //B2ERROR("Error, you specified invalid mode= " << mode);
1370  }
1371 
1372  return;
1373 
1374  }
1375 
1376  std::vector<int>
1377  CDCSensitiveDetector::WireId_in_hit_order(int id0, int id1, int nWires)
1378  {
1379  std::vector<int> list;
1380  int i0 = int(id0);
1381  int i1 = int(id1);
1382  if (abs(i0 - i1) * 2 < int(nWires)) {
1383  if (id0 < id1) {
1384  for (int i = id0; i <= id1; ++i)
1385  list.push_back(i);
1386  } else {
1387  for (int i = id0; i >= id1; i--) {
1388  list.push_back(i);
1389  }
1390  }
1391  } else {
1392  if (id0 < id1) {
1393  for (int i = id0; i >= 0; i--)
1394  list.push_back(i);
1395  for (int i = nWires - 1; i >= id1; i--)
1396  list.push_back(i);
1397  } else {
1398  for (int i = id0; i < nWires; ++i)
1399  list.push_back(i);
1400  for (int i = 0; i <= id1; ++i)
1401  list.push_back(i);
1402  }
1403  }
1404 
1405  return list;
1406  }
1407 
1408  G4double CDCSensitiveDetector::ClosestApproach(const G4ThreeVector bwp, const G4ThreeVector fwp, const G4ThreeVector posIn,
1409  const G4ThreeVector posOut, G4ThreeVector& hitPosition, G4ThreeVector& wirePosition)//,G4double& transferT)
1410  {
1411 
1412  TVector3 tbwp(bwp.x(), bwp.y(), bwp.z());
1413  TVector3 tfwp(fwp.x(), fwp.y(), fwp.z());
1414  TVector3 tposIn(posIn.x(), posIn.y(), posIn.z());
1415  TVector3 tposOut(posOut.x(), posOut.y(), posOut.z());
1416  TVector3 thitPosition(0., 0., 0.);
1417  TVector3 twirePosition(0., 0., 0.);
1418 
1419  // G4double distance = m_cdcgp.ClosestApproach(tbwp, tfwp, tposIn, tposOut, thitPosition, twirePosition);
1420  G4double distance = CDC::ClosestApproach(tbwp, tfwp, tposIn, tposOut, thitPosition, twirePosition);
1421 
1422  hitPosition.setX(thitPosition.x());
1423  hitPosition.setY(thitPosition.y());
1424  hitPosition.setZ(thitPosition.z());
1425 
1426  wirePosition.setX(twirePosition.x());
1427  wirePosition.setY(twirePosition.y());
1428  wirePosition.setZ(twirePosition.z());
1429 
1430  return distance;
1431  }
1432 
1433 
1434  //The following-to-end is for setting of left/right flag modified for tracking
1436  {
1437  if (!m_modifiedLeftRightFlag) return;
1438 
1439  // std::cout <<"#posHits,#negHits= " << m_nPosHits <<" "<< m_nNegHits << std::endl;
1440 
1441  // Get SimHit array and relation betw. MC and SimHit
1442  // N.B. MCParticle is incomplete at this stage; the relation betw it and
1443  // simHit is Okay.
1444  // MCParticle will be completed after all sub-detectors' EndOfEvent calls.
1445  RelationArray mcPartToSimHits(m_MCParticles, m_CDCSimHits);
1446  int nRelationsMinusOne = mcPartToSimHits.getEntries() - 1;
1447 
1448  if (nRelationsMinusOne == -1) return;
1449 
1450  // std::cout <<"#simHits= " << m_CDCSimHits.getEntries() << std::endl;
1451  // std::cout <<"#MCParticles= " << m_MCParticles.getEntries() << std::endl;
1452  // std::cout <<"#mcPartToSimHits= " << mcPartToSimHits.getEntries() << std::endl;
1453 
1454  //reset some of negative weights to positive; this is needed for the hits
1455  //created by secondary particles whose track-lengths get larger than the
1456  //threshold (set by the user) during G4 swimming (i.e. the weights are
1457  //first set to negative as far as the track-lengths are shorther than the
1458  //threshold; set to positive when the track-lengths exceed the threshold).
1459 
1460  size_t iRelation = 0;
1461  int trackIdOld = INT_MAX;
1462  // std::cout << "INT_MAX= " << INT_MAX << std::endl;
1463  m_hitWithPosWeight.clear();
1464  m_hitWithNegWeight.clear();
1465 
1466  for (int it = nRelationsMinusOne; it >= 0; --it) {
1467  RelationElement& mcPartToSimHit = const_cast<RelationElement&>(mcPartToSimHits[it]);
1468  size_t nRelatedHits = mcPartToSimHit.getSize();
1469  if (nRelatedHits > 1) B2FATAL("CDCSensitiveDetector::EndOfEvent: MCParticle<-> CDCSimHit relation is not one-to-one !");
1470 
1471  unsigned short trackId = mcPartToSimHit.getFromIndex();
1472  RelationElement::weight_type weight = mcPartToSimHit.getWeight(iRelation);
1473  if (weight > 0.) {
1474  trackIdOld = trackId;
1475  } else if (weight <= 0. && trackId == trackIdOld) {
1476  // RelationElement::index_type iSimHit = mcPartToSimHit.getToIndex(iRelation);
1477  weight *= -1.;
1478  mcPartToSimHit.setToIndex(mcPartToSimHit.getToIndex(iRelation), weight);
1479  trackIdOld = trackId;
1480  // std::cout <<"trackId,,iSimHit,wgtafterreset= "<< trackId <<" "<< iSimHit <<" "<< mcPartToSimHit.getWeight(iRelation) << std::endl;
1481  }
1482 
1483  CDCSimHit* sHit = m_CDCSimHits[mcPartToSimHit.getToIndex(iRelation)];
1484 
1485  if (weight > 0.) {
1486  m_hitWithPosWeight.insert(std::pair<unsigned short, CDCSimHit*>(sHit->getWireID().getISuperLayer(), sHit));
1487  } else {
1488  m_hitWithNegWeight.push_back(sHit);
1489  }
1490  }
1491 
1492  /*
1493  // std::cout <<"m_hitWithPosWeight.size= " << m_hitWithPosWeight.size() << std::endl;
1494  for(int i=0; i<9; ++i) {
1495  // if (m_hitWithPosWeight.find(i) != m_hitWithPosWeight.end()) {
1496  // std::cout << i << " found" << std::endl;
1497  // }
1498  m_posWeightMapItBegin.push_back(m_hitWithPosWeight.find(i));
1499  m_posWeightMapItEnd.push_back(m_hitWithPosWeight.find(i+1));
1500  }
1501  */
1502 
1503  //reassign L/R flag
1505 
1506  //reset all weights positive; this is required for completing MCParticle object at the EndOfEvent action of FullSim
1507  // is this part really needed ??? check again !
1508  for (int it = 0; it <= nRelationsMinusOne; ++it) {
1509  RelationElement& mcPartToSimHit = const_cast<RelationElement&>(mcPartToSimHits[it]);
1510  RelationElement::weight_type weight = mcPartToSimHit.getWeight(iRelation);
1511  if (weight < 0.) {
1512  mcPartToSimHit.setToIndex(mcPartToSimHit.getToIndex(iRelation), -1.*weight);
1513  }
1514  }
1515 
1516  }
1517 
1518 
1520  {
1521  CDCSimHit* sHit = nullptr;
1522  WireID sWireId; // = WireID();
1523  TVector3 sPos; // = TVector3();
1524 
1525  CDCSimHit* pHit = nullptr;
1526  WireID pWireId; // = WireID();
1527  // double minDistance2 = DBL_MAX;
1528  // double distance2 = DBL_MAX;
1529  // unsigned short bestNeighb = 0;
1530  // unsigned short neighb = 0;
1531 
1532  // std::multimap<unsigned short, CDCSimHit*>::iterator pItBegin = m_hitWithPosWeight.begin();
1533  // std::multimap<unsigned short, CDCSimHit*>::iterator pItEnd = m_hitWithPosWeight.end();
1534 
1535  // unsigned short sClayer = 0;
1536  // unsigned short sSuperLayer = 0;
1537  // unsigned short sLayer = 0;
1538  // unsigned short sWire = 0;
1539  // CDCSimHit* fHit = nullptr;
1540 
1541  //Find a primary track close to the input 2'ndary hit in question
1542  for (std::vector<CDCSimHit*>::iterator nIt = m_hitWithNegWeight.begin(), nItEnd = m_hitWithNegWeight.end(); nIt != nItEnd; ++nIt) {
1543 
1544  sHit = *nIt;
1545  sPos = sHit->getPosTrack();
1546  sWireId = sHit->getWireID();
1547  // sClayer = sWireId.getICLayer();
1548  // sSuperLayer = sWireId.getISuperLayer();
1549  // sLayer = sWireId.getILayer();
1550  // sWire = sWireId.getIWire();
1551  // fHit = sHit;
1552  unsigned short sClayer = sWireId.getICLayer();
1553  unsigned short sSuperLayer = sWireId.getISuperLayer();
1554  unsigned short sLayer = sWireId.getILayer();
1555  unsigned short sWire = sWireId.getIWire();
1556  CDCSimHit* fHit = sHit;
1557 
1558  std::multimap<unsigned short, CDCSimHit*>::iterator pItBegin = m_hitWithPosWeight.find(sSuperLayer);
1559  std::multimap<unsigned short, CDCSimHit*>::iterator pItEnd = m_hitWithPosWeight.find(sSuperLayer + 1);
1560  /*
1561  if (sSuperLayer <= 8) {
1562  pItBegin = m_posWeightMapItBegin.at(sSuperLayer);
1563  pItEnd = m_posWeightMapItEnd.at(sSuperLayer);
1564  } else {
1565  B2FATAL("CDCSensitiveDetector::EndOfEvent: invalid super-layer id ! " << sSuperLayer);
1566  }
1567  */
1568 
1569  double minDistance2 = DBL_MAX;
1570  // bestNeighb = 0;
1571 
1572  /* for (std::multimap<unsigned short, CDCSimHit*>::iterator pIt = m_hitWithPosWeight.begin(); pIt != m_hitWithPosWeight.end(); ++pIt) {
1573  std::cout <<"superLyr#= " << pIt->first << std::endl;
1574  }
1575  */
1576 
1577  for (std::multimap<unsigned short, CDCSimHit*>::iterator pIt = pItBegin; pIt != pItEnd; ++pIt) {
1578 
1579  //scan hits in the same/neighboring cells
1580  pHit = pIt->second;
1581  pWireId = pHit->getWireID();
1582  // neigh = areNeighbors(sWireId, pWireId);
1583  unsigned short neighb = areNeighbors(sClayer, sSuperLayer, sLayer, sWire, pWireId);
1584  if (neighb != 0 || pWireId == sWireId) {
1585  double distance2 = (pHit->getPosTrack() - sPos).Mag2();
1586  if (distance2 < minDistance2) {
1587  fHit = pHit;
1588  minDistance2 = distance2;
1589  // bestNeighb = neighb;
1590  }
1591  }
1592  }
1593 
1594  //reassign LR using the momentum-direction of the primary particle found
1595  unsigned short lR = m_cdcgp->getNewLeftRightRaw(sHit->getPosWire(),
1596  sHit->getPosTrack(),
1597  fHit->getMomentum());
1598  // unsigned short bflr = sHit->getLeftRightPassage();
1599  sHit->setLeftRightPassage(lR);
1600  // std::cout <<"neighb, bfaf lrs, minDistance= " << bestNeighb <<" "<<" "<< bflr <<" "<< sHit->getLeftRightPassage() <<" "<< std::scientific << sqrt(minDistance2) << std::endl;
1601  }
1602  }
1603 
1604 
1605  unsigned short CDCSensitiveDetector::areNeighbors(const WireID& wireId, const WireID& otherWireId) const
1606  {
1607  //require within the same super-layer
1608  if (otherWireId.getISuperLayer() != wireId.getISuperLayer()) return 0;
1609 
1610  const signed short iWire = wireId.getIWire();
1611  const signed short iOtherWire = otherWireId.getIWire();
1612  const signed short iCLayer = wireId.getICLayer();
1613  const signed short iOtherCLayer = otherWireId.getICLayer();
1614 
1615  //require nearby wire
1616  if (iWire == iOtherWire) {
1617  } else if (iWire == (iOtherWire + 1) % static_cast<signed short>(m_cdcgp->nWiresInLayer(iOtherCLayer))) {
1618  } else if ((iWire + 1) % static_cast<signed short>(m_cdcgp->nWiresInLayer(iCLayer)) == iOtherWire) {
1619  } else {
1620  return 0;
1621  }
1622  // std::cout <<"iCLayer,iLayer,nShifts= " << iCLayer <<" "<< iLayer <<" "<< nShifts(iCLayer) << std::endl;
1623 
1624  signed short iLayerDifference = otherWireId.getILayer() - wireId.getILayer();
1625  if (abs(iLayerDifference) > 1) return 0;
1626 
1627  if (iLayerDifference == 0) {
1628  if (iWire == (iOtherWire + 1) % static_cast<signed short>(m_cdcgp->nWiresInLayer(iCLayer))) return CW_NEIGHBOR;
1629  else if ((iWire + 1) % static_cast<signed short>(m_cdcgp->nWiresInLayer(iCLayer)) == iOtherWire) return CCW_NEIGHBOR;
1630  else return 0;
1631  } else if (iLayerDifference == -1) {
1632  // const CCWInfo deltaShift = otherLayer.getShift() - layer.getShift();
1633  const signed short deltaShift = m_cdcgp->getShiftInSuperLayer(otherWireId.getISuperLayer(), otherWireId.getILayer()) -
1635  // std::cout <<"in deltaShift,iOtherWire,iWire= " << deltaShift <<" "<< iOtherWire <<" "<< iWire << std::endl;
1636  if (iWire == iOtherWire) {
1637  if (deltaShift == CW) return CW_IN_NEIGHBOR;
1638  else if (deltaShift == CCW) return CCW_IN_NEIGHBOR;
1639  else return 0;
1640  } else if (iWire == (iOtherWire + 1) % static_cast<signed short>(m_cdcgp->nWiresInLayer(iOtherCLayer))) {
1641  if (deltaShift == CCW) return CW_IN_NEIGHBOR;
1642  else return 0;
1643  } else if ((iWire + 1) % static_cast<signed short>(m_cdcgp->nWiresInLayer(iCLayer)) == iOtherWire) {
1644  if (deltaShift == CW) return CCW_IN_NEIGHBOR;
1645  else return 0;
1646  } else return 0;
1647  } else if (iLayerDifference == 1) {
1648  // const CCWInfo deltaShift = otherLayer.getShift() - layer.getShift();
1649  const signed short deltaShift = m_cdcgp->getShiftInSuperLayer(otherWireId.getISuperLayer(), otherWireId.getILayer()) -
1651  // std::cout <<"out deltaShift,iOtherWire,iWire= " << deltaShift <<" "<< iOtherWire <<" "<< iWire << std::endl;
1652  if (iWire == iOtherWire) {
1653  if (deltaShift == CW) return CW_OUT_NEIGHBOR;
1654  else if (deltaShift == CCW) return CCW_OUT_NEIGHBOR;
1655  else return 0;
1656  } else if (iWire == (iOtherWire + 1) % static_cast<signed short>(m_cdcgp->nWiresInLayer(iOtherCLayer))) {
1657  if (deltaShift == CCW) return CW_OUT_NEIGHBOR;
1658  else return 0;
1659  } else if ((iWire + 1) % static_cast<signed short>(m_cdcgp->nWiresInLayer(iCLayer)) == iOtherWire) {
1660  if (deltaShift == CW) return CCW_OUT_NEIGHBOR;
1661  else return 0;
1662  } else return 0;
1663  } else return 0;
1664 
1665  }
1666 
1667  unsigned short CDCSensitiveDetector::areNeighbors(unsigned short iCLayer, unsigned short iSuperLayer, unsigned short iLayer,
1668  unsigned short iWire, const WireID& otherWireId) const
1669  {
1670  //require within the same super-layer
1671  if (otherWireId.getISuperLayer() != iSuperLayer) return 0;
1672 
1673  const signed short iOtherWire = otherWireId.getIWire();
1674  const signed short iOtherCLayer = otherWireId.getICLayer();
1675 
1676  //require nearby wire
1677  if (iWire == iOtherWire) {
1678  } else if (iWire == (iOtherWire + 1) % static_cast<signed short>(m_cdcgp->nWiresInLayer(iOtherCLayer))) {
1679  } else if ((iWire + 1) % static_cast<signed short>(m_cdcgp->nWiresInLayer(iCLayer)) == iOtherWire) {
1680  } else {
1681  return 0;
1682  }
1683 
1684  // std::cout <<"iCLayer,iLayer,nShifts= " << iCLayer <<" "<< iLayer <<" "<< nShifts(iCLayer) << std::endl;
1685  signed short iLayerDifference = otherWireId.getILayer() - iLayer;
1686  if (abs(iLayerDifference) > 1) return 0;
1687 
1688  if (iLayerDifference == 0) {
1689  if (iWire == (iOtherWire + 1) % static_cast<signed short>(m_cdcgp->nWiresInLayer(iCLayer))) return CW_NEIGHBOR;
1690  else if ((iWire + 1) % static_cast<signed short>(m_cdcgp->nWiresInLayer(iCLayer)) == iOtherWire) return CCW_NEIGHBOR;
1691  else return 0;
1692  } else if (iLayerDifference == -1) {
1693  // const CCWInfo deltaShift = otherLayer.getShift() - layer.getShift();
1694  const signed short deltaShift = m_cdcgp->getShiftInSuperLayer(otherWireId.getISuperLayer(), otherWireId.getILayer()) -
1695  m_cdcgp->getShiftInSuperLayer(iSuperLayer, iLayer);
1696  // std::cout <<"in deltaShift,iOtherWire,iWire= " << deltaShift <<" "<< iOtherWire <<" "<< iWire << std::endl;
1697  if (iWire == iOtherWire) {
1698  if (deltaShift == CW) return CW_IN_NEIGHBOR;
1699  else if (deltaShift == CCW) return CCW_IN_NEIGHBOR;
1700  else return 0;
1701  } else if (iWire == (iOtherWire + 1) % static_cast<signed short>(m_cdcgp->nWiresInLayer(iOtherCLayer))) {
1702  if (deltaShift == CCW) return CW_IN_NEIGHBOR;
1703  else return 0;
1704  } else if ((iWire + 1) % static_cast<signed short>(m_cdcgp->nWiresInLayer(iCLayer)) == iOtherWire) {
1705  if (deltaShift == CW) return CCW_IN_NEIGHBOR;
1706  else return 0;
1707  } else return 0;
1708  } else if (iLayerDifference == 1) {
1709  // const CCWInfo deltaShift = otherLayer.getShift() - layer.getShift();
1710  const signed short deltaShift = m_cdcgp->getShiftInSuperLayer(otherWireId.getISuperLayer(), otherWireId.getILayer()) -
1711  m_cdcgp->getShiftInSuperLayer(iSuperLayer, iLayer);
1712  // std::cout <<"out deltaShift,iOtherWire,iWire= " << deltaShift <<" "<< iOtherWire <<" "<< iWire << std::endl;
1713  if (iWire == iOtherWire) {
1714  if (deltaShift == CW) return CW_OUT_NEIGHBOR;
1715  else if (deltaShift == CCW) return CCW_OUT_NEIGHBOR;
1716  else return 0;
1717  } else if (iWire == (iOtherWire + 1) % static_cast<signed short>(m_cdcgp->nWiresInLayer(iOtherCLayer))) {
1718  if (deltaShift == CCW) return CW_OUT_NEIGHBOR;
1719  else return 0;
1720  } else if ((iWire + 1) % static_cast<signed short>(m_cdcgp->nWiresInLayer(iCLayer)) == iOtherWire) {
1721  if (deltaShift == CW) return CCW_OUT_NEIGHBOR;
1722  else return 0;
1723  } else return 0;
1724  } else return 0;
1725 
1726  }
1727 
1729 } // namespace Belle2
Example Detector.
Definition: CDCSimHit.h:22
void setLeftRightPassageRaw(int minusOneOrZeroOrOne)
The method to set new left/right info. for digitization.
Definition: CDCSimHit.h:162
void setPosOut(TVector3 posOut)
The method to set position of post-step.
Definition: CDCSimHit.h:136
TVector3 getPosWire() const
The method to get position on wire.
Definition: CDCSimHit.h:205
void setPosFlag(int zeroOrOne)
The method to set position flag.
Definition: CDCSimHit.h:155
void setPosWire(TVector3 posWire)
The method to set position on wire.
Definition: CDCSimHit.h:120
WireID getWireID() const
Getter for WireID object.
Definition: CDCSimHit.h:178
void setWireID(int iCLayerID, int iWireID)
Setter for Wire ID.
Definition: CDCSimHit.h:85
void setGlobalTime(double globalTime)
The method to set global time.
Definition: CDCSimHit.h:103
void setTrackId(int trackId)
The method to set track id.
Definition: CDCSimHit.h:91
void setPDGCode(int pdg)
The method to set PDG code.
Definition: CDCSimHit.h:94
TVector3 getMomentum() const
The method to get momentum.
Definition: CDCSimHit.h:199
void setEnergyDep(double edep)
The method to set deposited energy.
Definition: CDCSimHit.h:106
void setDriftLength(double driftLength)
The method to set drift length.
Definition: CDCSimHit.h:97
void setStepLength(double stepLength)
The method to set step length.
Definition: CDCSimHit.h:109
void setMomentum(TVector3 momentum)
The method to set momentum.
Definition: CDCSimHit.h:112
void setFlightTime(double flightTime)
The method to set flight time.
Definition: CDCSimHit.h:100
TVector3 getPosTrack() const
The method to get position on the track.
Definition: CDCSimHit.h:223
void setPosTrack(TVector3 posTrack)
The method to set position on the track.
Definition: CDCSimHit.h:144
void setPosIn(TVector3 posIn)
The method to set position of pre-step.
Definition: CDCSimHit.h:128
void setLeftRightPassage(int minusOneOrZeroOrOne)
The method to set new left/right info. for tracking.
Definition: CDCSimHit.h:170
unsigned short getOldLeftRight(const TVector3 &posOnWire, const TVector3 &posOnTrack, const TVector3 &momentum) const
Returns old left/right.
const TVector3 wireBackwardPosition(int layerId, int cellId, EWirePosition set=c_Base) const
Returns the backward position of the input sense wire.
unsigned short getNewLeftRightRaw(const TVector3 &posOnWire, const TVector3 &posOnTrack, const TVector3 &momentum) const
Returns new left/right_raw.
void getWireSagEffect(EWirePosition set, unsigned layerID, unsigned cellID, double zw, double &ywb_sag, double &ywf_sag) const
Compute effects of the sense wire sag.
const TVector3 wireForwardPosition(int layerId, int cellId, EWirePosition set=c_Base) const
Returns the forward position of the input sense wire.
unsigned nWiresInLayer(int layerId) const
Returns wire numbers in a layer.
signed short getShiftInSuperLayer(unsigned short iSuperLayer, unsigned short iLayer) const
Returns shift in the super-layer.
static CDCGeometryPar & Instance(const CDCGeometry *=nullptr)
Static method to get a reference to the CDCGeometryPar instance.
unsigned cellId(unsigned layerId, const TVector3 &position) const
The method to get cell id based on given layer id and the position.
const signed short CW_NEIGHBOR
Constant for clockwise.
G4double m_thresholdEnergyDeposit
Threshold energy deposit to be stored.
const signed short CCW_NEIGHBOR
Constant for counterclockwise.
CDCGeometryPar * m_cdcgp
Pointer to CDCGeometryPar object.
const signed short CW_IN_NEIGHBOR
Constant for clockwise inwards.
std::multimap< unsigned short, CDCSimHit * > m_hitWithPosWeight
Map containing hits with positive weight.
const signed short CCW_OUT_NEIGHBOR
Constant for counterclockwise outwards.
G4bool m_wireSag
Switch to activate wire sag effect.
StoreArray< CDCSimHit > m_CDCSimHits
CDC simulation hits.
G4double m_thresholdKineticEnergy
Threshold kinetic energy to be stored.
const signed short CW_OUT_NEIGHBOR
Constant for clockwise outwards.
const signed short CCW
Constant for counterclockwise orientation.
const signed short CCW_IN_NEIGHBOR
Constant for counterclockwise inwards.
G4bool m_modifiedLeftRightFlag
Switch for left/right flag modified for tracking.
G4int m_magneticField
Magnetic field is on or off.
int m_hitNumber
The current number of created hits in an event.
G4double m_brot[3][3]
a rotation matrix.
std::vector< CDCSimHit * > m_hitWithNegWeight
Vector containing hits with negative weight.
G4int m_nonUniformField
Magnetic field is uniform or non-uniform.
StoreArray< MCParticle > m_MCParticles
MC particles.
const signed short CW
Constant for clockwise orientation.
The Class for CDC Simulation Control Parameters.
bool getModLeftRightFlag() const
Get modified left/right flag.
double getMinTrackLength() const
Get minimum track length.
double getThresholdEnergyDeposit() const
Get threshold for Energy Deposit;.
static CDCSimControlPar & getInstance()
Static method to get a reference to the CDCSimControlPar instance.
bool getWireSag() const
Get wiresag flag.
Helix parameter class.
Definition: Helix.h:48
This class provides a set of constants for the framework.
Definition: Const.h:34
Low-level class to create/modify relations between StoreArrays.
Definition: RelationArray.h:62
int getEntries() const
Get the number of elements.
void add(index_type from, index_type to, weight_type weight=1.0)
Add a new element to the relation.
Class to store a single element of a relation.
index_type getFromIndex() const
Get index we point from.
index_type getToIndex(size_t n=0) const
Get nth index we point to.
void setToIndex(index_type to, weight_type weight=1.0)
Set index we point to, converts relation to 1:1 and discards all existing to-indices.
float weight_type
type used for weights.
size_t getSize() const
Get number of indices we points to.
weight_type getWeight(size_t n=0) const
Get nth weight we point to.
static void registerMCParticleRelation(const std::string &name, RelationArray::EConsolidationAction ignoreAction=RelationArray::c_negativeWeight)
Register an relation involving MCParticles.
static Payload getInfo(Carrier &obj)
Static function to just return UserInformation attached to the obj of type Carrier.
Definition: UserInfo.h:100
bool registerRelationTo(const StoreArray< TO > &toArray, DataStore::EDurability durability=DataStore::c_Event, DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut, const std::string &namedRelation="") const
Register a relation to the given StoreArray.
Definition: StoreArray.h:140
Class to identify a wire inside the CDC.
Definition: WireID.h:34
unsigned short getICLayer() const
Getter for continuous layer numbering.
Definition: WireID.cc:24
unsigned short getIWire() const
Getter for wire within the layer.
Definition: WireID.h:145
unsigned short getISuperLayer() const
Getter for Super-Layer.
Definition: WireID.h:130
unsigned short getILayer() const
Getter for layer within the Super-Layer.
Definition: WireID.h:136
bool step(G4Step *aStep, G4TouchableHistory *history) override
Process each step and calculate variables defined in CDCB4VHit.
void setModifiedLeftRightFlag()
set left/right flag modified for tracking
unsigned short areNeighbors(const WireID &wireId, const WireID &otherWireId) const
Check if neighboring cell in the same super-layer; essentially a copy from cdcLocalTracking/mclookup.
void EndOfEvent(G4HCofThisEvent *) override
Do what you want to do at the beginning of each event (why this is not called ?)
void for_Rotat(const G4double bfld[3])
Calculates a rotation matrix.
void HELWIR(const G4double xwb4, const G4double ywb4, const G4double zwb4, const G4double xwf4, const G4double ywf4, const G4double zwf4, const G4double xp, const G4double yp, const G4double zp, const G4double px, const G4double py, const G4double pz, const G4double B_kG[3], const G4double charge, const G4int ntryMax, G4double &distance, G4double q2[3], G4double q1[3], G4double q3[3], G4int &ntry)
Calculate closest points between helix and wire.
CDCSensitiveDetector(G4String name, G4double thresholdEnergyDeposit, G4double thresholdKineticEnergy)
Constructor.
void CellBound(const G4int layerId, const G4int ic1, const G4int ic2, const G4double venter[6], const G4double vexit[6], const G4double s1, const G4double s2, G4double xint[6], G4double &sint, G4int &iflag)
Calculate intersection of track with cell boundary.
void Rotat(G4double &x, G4double &y, G4double &z, const int mode)
Translation method.
void saveSimHit(const G4int layerId, const G4int wireId, const G4int trackID, const G4int pid, const G4double distance, const G4double tof, const G4double edep, const G4double stepLength, const G4ThreeVector &mom, const G4ThreeVector &posW, const G4ThreeVector &posIn, const G4ThreeVector &posOut, const G4ThreeVector &posTrack, const G4int lr, const G4int NewLrRaw, const G4int NewLr, const G4double speed, const G4double hitWeight)
Save CDCSimHit into datastore.
void Mvopr(const G4int ndim, const G4double b[3], const G4double m[3][3], const G4double a[3], G4double c[3], const G4int mode)
Calculate the result of a matrix times vector.
void Initialize(G4HCofThisEvent *) override
Register CDC hits collection into G4HCofThisEvent.
G4double ClosestApproach(G4ThreeVector bwp, G4ThreeVector fwp, G4ThreeVector posIn, G4ThreeVector posOut, G4ThreeVector &hitPosition, G4ThreeVector &wirePosition)
Assume line track to calculate distance between track and wire (drift length).
void GCUBS(const G4double x, const G4double y, const G4double d1, const G4double d2, G4double a[4])
void reAssignLeftRightInfo()
Re-assign left/right info.
std::vector< int > WireId_in_hit_order(int id0, int id1, int nWires)
Sort wire id.
double eval(const std::vector< double > &spl, const std::vector< double > &vals, double x)
Evaluate spline (zero order or first order) in point x.
Definition: tools.h:115
double ClosestApproach(const TVector3 &bwp, const TVector3 &fwp, const TVector3 &posIn, const TVector3 &posOut, TVector3 &hitPosition, TVector3 &wirePosition)
Returns a closest distance between a track and a wire.
Abstract base class for different kinds of events.