Belle II Software  release-08-01-10
CDCGeometryPar.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 <framework/gearbox/Gearbox.h>
10 #include <framework/gearbox/GearDir.h>
11 #include <framework/logging/Logger.h>
12 #include <framework/utilities/FileSystem.h>
13 
14 #include <cdc/geometry/CDCGeometryPar.h>
15 #include <cdc/geometry/CDCGeoControlPar.h>
16 #include <cdc/simulation/CDCSimControlPar.h>
17 #include <cdc/utilities/OpenFile.h>
18 
19 //#include <float.h>
20 
21 #include <cmath>
22 #include <boost/format.hpp>
23 //#include <iostream>
24 #include <iomanip>
25 
26 #include <boost/iostreams/filtering_stream.hpp>
27 //#include <boost/iostreams/device/file.hpp>
28 //#include <boost/iostreams/filter/gzip.hpp>
29 
30 #include <Math/ChebyshevPol.h>
31 
32 using namespace std;
33 using namespace boost;
34 using namespace Belle2;
35 using namespace CDC;
36 
37 CDCGeometryPar* CDCGeometryPar::m_B4CDCGeometryParDB = 0;
38 
39 CDCGeometryPar& CDCGeometryPar::Instance(const CDCGeometry* geom)
40 {
41  if (!m_B4CDCGeometryParDB) m_B4CDCGeometryParDB = new CDCGeometryPar(geom);
42  return *m_B4CDCGeometryParDB;
43 }
44 
45 CDCGeometryPar::CDCGeometryPar(const CDCGeometry* geom)
46 {
47 
48  CDCGeoControlPar& gcp = CDCGeoControlPar::getInstance();
49 
50  if (gcp.getT0InputType()) {
51  m_t0FromDB = new DBObjPtr<CDCTimeZeros>;
52  if ((*m_t0FromDB).isValid()) {
53  (*m_t0FromDB).addCallback(this, &CDCGeometryPar::setT0);
54  }
55  }
56 
57  if (gcp.getBwInputType()) {
58  m_badWireFromDB = new DBObjPtr<CDCBadWires>;
59  if ((*m_badWireFromDB).isValid()) {
60  (*m_badWireFromDB).addCallback(this, &CDCGeometryPar::setBadWire);
61  }
62  }
63 
64  if (gcp.getPropSpeedInputType()) {
65  m_propSpeedFromDB = new DBObjPtr<CDCPropSpeeds>;
66  if ((*m_propSpeedFromDB).isValid()) {
67  (*m_propSpeedFromDB).addCallback(this, &CDCGeometryPar::setPropSpeed);
68  }
69  }
70 
71  if (gcp.getTwInputType()) {
72  m_timeWalkFromDB = new DBObjPtr<CDCTimeWalks>;
73  if ((*m_timeWalkFromDB).isValid()) {
74  (*m_timeWalkFromDB).addCallback(this, &CDCGeometryPar::setTW);
75  }
76  }
77 
78  if (gcp.getXtInputType()) {
79  m_xtRelFromDB = new DBObjPtr<CDCXtRelations>;
80  if ((*m_xtRelFromDB).isValid()) {
81  (*m_xtRelFromDB).addCallback(this, &CDCGeometryPar::setXtRel);
82  }
83  }
84 
85  if (gcp.getSigmaInputType()) {
86  m_sResolFromDB = new DBObjPtr<CDCSpaceResols>;
87  if ((*m_sResolFromDB).isValid()) {
88  (*m_sResolFromDB).addCallback(this, &CDCGeometryPar::setSResol);
89  }
90  }
91 
92  if (gcp.getFFactorInputType()) {
93  m_fFactorFromDB = new DBObjPtr<CDCFudgeFactorsForSigma>;
94  if ((*m_fFactorFromDB).isValid()) {
95  (*m_fFactorFromDB).addCallback(this, &CDCGeometryPar::setFFactor);
96  }
97  }
98 
99  if (gcp.getChMapInputType()) {
100  m_chMapFromDB = new DBArray<CDCChannelMap>;
101  if ((*m_chMapFromDB).isValid()) {
102  (*m_chMapFromDB).addCallback(this, &CDCGeometryPar::setChMap);
103  }
104  }
105 
106  if (gcp.getDisplacementInputType()) {
107  m_displacementFromDB = new DBArray<CDCDisplacement>;
108  if ((*m_displacementFromDB).isValid()) {
109  (*m_displacementFromDB).addCallback(this, &CDCGeometryPar::setDisplacement);
110  }
111  }
112 
113  if (gcp.getAlignmentInputType()) {
114  m_alignmentFromDB = new DBObjPtr<CDCAlignment>;
115  if ((*m_alignmentFromDB).isValid()) {
116  (*m_alignmentFromDB).addCallback(this, &CDCGeometryPar::setWirPosAlignParams);
117  }
118  }
119 
120  if (gcp.getMisalignment()) {
121  if (gcp.getMisalignmentInputType()) {
122  m_misalignmentFromDB = new DBObjPtr<CDCMisalignment>;
123  if ((*m_misalignmentFromDB).isValid()) {
124  (*m_misalignmentFromDB).addCallback(this, &CDCGeometryPar::setWirPosMisalignParams);
125  }
126  }
127  }
128 
129  //TODO in future: make a new (singleton?) class and move all EDepToADC things there.
130  if (gcp.getEDepToADCInputType()) {
131  m_eDepToADCConversionsFromDB = new OptionalDBObjPtr<CDCEDepToADCConversions>;
132  if ((*m_eDepToADCConversionsFromDB).isValid()) {
133  (*m_eDepToADCConversionsFromDB).addCallback(this, &CDCGeometryPar::setEDepToADCConversions);
134  }
135  }
136 
137  clear();
138  if (geom) {
139  // B2INFO("CDCGeometryPar: Read Geometry object");
140  readFromDB(*geom);
141  } else {
142  // std::cout <<"readcalled" << std::endl;
143  // read();
144  // B2FATAL("CDCGeometryPar: Strange that readFromDB is not called !");
145  B2WARNING("CDCGeometryPar: Strange that readFromDB is not called! Please make sure that CDC is included in Geometry.");
146  }
147 }
148 
149 CDCGeometryPar::~CDCGeometryPar()
150 {
151  // B2INFO("CDCGeometryPar: destructor called");
152  // if (m_t0FromDB) delete m_t0FromDB;
153  // if (m_badWireFromDB) delete m_badWireFromDB;
154  // if (m_propSpeedFromDB) delete m_propSpeedFromDB;
155  // if (m_timeWalkFromDB) delete m_timeWalkFromDB;
156  // if (m_xtRelFromDB) delete m_xtRelFromDB;
157  // if (m_sResolFromDB) delete m_sResolFromDB;
158  // if (m_chMapFromDB) delete [] m_chMapFromDB;
159  // if (m_displacementFromDB) delete [] m_displacementFromDB;
160  // if (m_chMapFromDB) delete m_chMapFromDB;
161  // if (m_displacementFromDB) delete m_displacementFromDB;
162  // if (m_alignmentFromDB) delete m_alignmentFromDB;
163  // if (m_misalignmentFromDB) delete m_misalignmentFromDB;
164  // B2INFO("CDCGeometryPar: destructor ended");
165 }
166 
167 void CDCGeometryPar::clear()
168 {
169  m_version = "unknown";
170  m_nSLayer = 0;
171  m_nFLayer = 0;
172  m_senseWireDiameter = 0.0;
173  m_senseWireTension = 0.0;
174  m_senseWireDensity = 0.0;
175  m_fieldWireDiameter = 0.0;
176 
177  m_tdcOffset = 0; //not used; to be removed later
178  m_clockFreq4TDC = 0.0;
179  m_tdcBinWidth = 0.0;
180  m_nominalDriftV = 0.0;
181  m_nominalPropSpeed = 0.0;
182  m_nominalSpaceResol = 0.0;
183 
184  for (unsigned i = 0; i < 4; ++i) {
185  m_rWall[i] = 0;
186  for (unsigned j = 0; j < 2; ++j)
187  m_zWall[i][j] = 0;
188  }
189  for (unsigned i = 0; i < c_maxNSenseLayers; ++i) {
190  m_rSLayer[i] = 0;
191  m_zSForwardLayer[i] = 0;
192  m_dzSForwardLayer[i] = 0;
193  m_zSBackwardLayer[i] = 0;
194  m_dzSBackwardLayer[i] = 0;
195  m_cellSize[i] = 0;
196  m_nWires[i] = 0;
197  m_offSet[i] = 0;
198  m_nShifts[i] = 0;
199  m_propSpeedInv[i] = 0.;
200  }
201  for (unsigned i = 0; i < c_maxNFieldLayers; ++i) {
202  m_rFLayer[i] = 0;
203  m_zFForwardLayer[i] = 0;
204  m_zFBackwardLayer[i] = 0;
205  }
206 
207  for (unsigned L = 0; L < c_maxNSenseLayers; ++L) {
208  for (unsigned C = 0; C < c_maxNDriftCells; ++C) {
209  for (unsigned i = 0; i < 3; ++i) {
210  m_FWirPos [L][C][i] = 0.;
211  m_BWirPos [L][C][i] = 0.;
212  m_FWirPosMisalign[L][C][i] = 0.;
213  m_BWirPosMisalign[L][C][i] = 0.;
214  m_FWirPosAlign [L][C][i] = 0.;
215  m_BWirPosAlign [L][C][i] = 0.;
216  }
217  for (unsigned i = 0; i < 7; ++i) {
218  m_eDepToADCParams[L][C][i] = 0.;
219  }
220  m_WireSagCoef [L][C] = 0.;
221  m_WireSagCoefMisalign[L][C] = 0.;
222  m_WireSagCoefAlign [L][C] = 0.;
223  m_t0 [L][C] = 0.;
224  }
225  }
226 
227  for (unsigned L = 0; L < c_maxNSenseLayers; ++L) {
228  for (unsigned i = 0; i < 2; ++i) {
229  for (unsigned alpha = 0; alpha < c_maxNAlphaPoints; ++alpha) {
230  for (unsigned theta = 0; theta < c_maxNThetaPoints; ++theta) {
231  for (unsigned xtparam = 0; xtparam < c_nXTParams; ++xtparam) {
232  m_XT[L][i][alpha][theta][xtparam] = 0.;
233  }
234 
235  for (unsigned sigmaparam = 0; sigmaparam < c_nSigmaParams; ++sigmaparam) {
236  m_Sigma[L][i][alpha][theta][sigmaparam] = 0.;
237  }
238  }
239  }
240  }
241  }
242 
243  for (unsigned board = 0; board < c_nBoards; ++board) {
244  for (unsigned i = 0; i < 2; ++i) {
245  m_timeWalkCoef[board][i] = 0.;
246  }
247  for (unsigned channel = 0; channel < 48; ++channel) {
248  m_boardAndChannelToWire[board][channel] = 0.;
249  }
250  }
251 
252  for (unsigned superLayer = 0; superLayer < c_nSuperLayers; ++superLayer) {
253  for (unsigned layer = 0; layer < 8; ++layer) {
254  m_shiftInSuperLayer[superLayer][layer] = 0;
255  }
256  }
257 
258 }
259 
260 void CDCGeometryPar::readFromDB(const CDCGeometry& geom)
261 {
262  m_globalPhiRotation = geom.getGlobalPhiRotation();
263  // m_globalPhiRotation = geom.getGlobalOffsetC();
264 
265  // Get inner wall parameters
266  m_rWall[0] = geom.getInnerWall(2).getRmin();
267  m_zWall[0][0] = geom.getInnerWall(0).getZbwd();
268  m_zWall[0][1] = geom.getInnerWall(0).getZfwd();
269 
270  m_rWall[1] = geom.getInnerWall(0).getRmax();
271  m_zWall[1][0] = geom.getInnerWall(0).getZbwd();
272  m_zWall[1][1] = geom.getInnerWall(0).getZbwd();
273 
274  // Get outer wall parameters
275  m_rWall[2] = geom.getOuterWall(0).getRmin();
276  m_zWall[2][0] = geom.getOuterWall(0).getZbwd();
277  m_zWall[2][1] = geom.getOuterWall(0).getZfwd();
278 
279  m_rWall[3] = geom.getOuterWall(1).getRmax();
280  m_zWall[3][0] = geom.getOuterWall(0).getZbwd();
281  m_zWall[3][1] = geom.getOuterWall(0).getZfwd();
282 
283  // Get sense layers parameters
284  m_debug = CDCGeoControlPar::getInstance().getDebug();
285  m_nSLayer = geom.getNSenseLayers();
286 
287  m_materialDefinitionMode = CDCGeoControlPar::getInstance().getMaterialDefinitionMode();
288  // std::cout << m_materialDefinitionMode << std::endl;
289  if (m_materialDefinitionMode == 0) {
290  B2DEBUG(100, "CDCGeometryPar: Define a mixture of gases and wires in the tracking volume.");
291  } else if (m_materialDefinitionMode == 2) {
292  // B2INFO("CDCGeometryPar: Define all sense and field wires explicitly in the tracking volume.");
293  B2FATAL("CDCGeometryPar: Materialdefinition=2 is disabled for now.");
294  } else {
295  B2FATAL("CDCGeometryPar: Materialdefinition mode you specify is invalid.");
296  }
297 
298  // Get mode for wire z-position
299  m_senseWireZposMode = CDCGeoControlPar::getInstance().getSenseWireZposMode();
300  //Set z corrections (from input data)
301  B2DEBUG(100, "CDCGeometryPar: Sense wire z mode:" << m_senseWireZposMode);
302 
303  //
304  // The DB version should be implemented ASAP.
305  //
306  GearDir content = GearDir("/Detector/DetectorComponent[@name=\"CDC\"]/Content/");
307  GearDir gbxParams(content);
308  // if (m_senseWireZposMode == 1) readDeltaz(gbxParams);
309 
310 
311  //
312  // Sense wires.
313  //
314  for (const auto& sense : geom.getSenseLayers()) {
315  uint layerId = sense.getId();
316 
317  m_rSLayer[layerId] = sense.getR();
318  m_zSBackwardLayer[layerId] = sense.getZbwd();
319  m_zSForwardLayer[layerId] = sense.getZfwd();
320  m_nWires[layerId] = sense.getNWires();
321  m_nShifts[layerId] = sense.getNShifts();
322  m_offSet[layerId] = sense.getOffset();
323  m_cellSize[layerId] = 2 * M_PI * m_rSLayer[layerId] / (double) m_nWires[layerId];
324  m_dzSBackwardLayer[layerId] = sense.getDZbwd();
325  m_dzSForwardLayer[layerId] = sense.getDZfwd();
326 
327  //correction to z-position
328  if (m_senseWireZposMode == 0) {
329  } else if (m_senseWireZposMode == 1) {
330  // m_zSBackwardLayer[layerId] += m_bwdDz[layerId];
331  // m_zSForwardLayer [layerId] += m_fwdDz[layerId];
332  m_zSBackwardLayer[layerId] += m_dzSBackwardLayer[layerId];
333  m_zSForwardLayer [layerId] -= m_dzSForwardLayer [layerId];
334  } else {
335  B2FATAL("CDCGeometryPar: invalid wire z definition mode specified");
336  }
337 
338  //Set design sense-wire related params.
339  const int nWires = m_nWires[layerId];
340  for (int iCell = 0; iCell < nWires; ++iCell) {
341  setDesignWirParam(layerId, iCell);
342  }
343 
344  }
345 
346  // Get field layers parameters
347  for (const auto& field : geom.getFieldLayers()) {
348  uint layerId = field.getId();
349 
350  m_rFLayer[layerId] = field.getR();
351  m_zFBackwardLayer[layerId] = field.getZbwd();
352  m_zFForwardLayer[layerId] = field.getZfwd();
353  }
354 
355  // Get sense wire diameter
356  m_senseWireDiameter = geom.getSenseDiameter();
357 
358  // Get sense wire tension
359  m_senseWireTension = geom.getSenseTension();
360 
361  // // Get sense wire density
362  m_senseWireDensity = 19.3; // g/cm3 <- tentatively hard-coded here
363 
364  // Get field wire diameter
365  m_fieldWireDiameter = geom.getFieldDiameter();
366 
367  // Get information on the number of (super) layers etc.
368  m_nSenseWires = geom.getNSenseWires();
369  m_nFieldWires = geom.getNFieldWires();
370  m_maxNSenseLayers = geom.getNumberOfSenseLayers();
371  m_maxNFieldLayers = geom.getNumberOfFieldLayers();
372  m_maxNSuperLayers = geom.getMaxNumberOfSuperLayers();
373  m_firstLayerOffset = geom.getOffsetOfFirstLayer();
374  m_firstSuperLayerOffset = geom.getOffsetOfFirstSuperLayer();
375  m_maxNCellsPerLayer = geom.getMaxNumberOfCellsPerLayer();
376 
377  //Set various quantities (should be moved to CDC.xml later...)
378  m_clockFreq4TDC = geom.getClockFrequency();
379  if (not m_clockSettings.isValid())
380  B2FATAL("HardwareClockSettings payloads are not valid.");
381  const double officialClockFreq4TDC = 2 * m_clockSettings->getAcceleratorRF(); // in GHz
382  if (abs(m_clockFreq4TDC - officialClockFreq4TDC) / m_clockFreq4TDC > 1.e-4) {
383  B2WARNING("ClockFreq4TDC changed from cdclocal " << scientific << setprecision(6) << m_clockFreq4TDC << " to official " <<
384  officialClockFreq4TDC << " (GHz) (difference larger than 0.01%)");
385  m_clockFreq4TDC = officialClockFreq4TDC;
386  }
387  B2DEBUG(100, "CDCGeometryPar: Clock freq. for TDC= " << m_clockFreq4TDC << " (GHz).");
388  m_tdcBinWidth = 1. / m_clockFreq4TDC; //in ns
389  B2DEBUG(100, "CDCGeometryPar: TDC bin width= " << m_tdcBinWidth << " (ns).");
390 
391  m_nominalDriftV = 4.e-3; //in cm/ns
392  m_nominalDriftVInv = 1. / m_nominalDriftV; //in ns/cm
393  m_nominalPropSpeed = 27.25; //in cm/nsec (Belle's result, provided by iwasaki san)
394 
395  m_nominalSpaceResol = geom.getNominalSpaceResolution();
396  CDCGeoControlPar& gcp = CDCGeoControlPar::getInstance();
397 
398  //Set displacement params. (from input data)
399  m_displacement = CDCGeoControlPar::getInstance().getDisplacement();
400  B2DEBUG(100, "CDCGeometryPar: Load displacement params. (=1); not load (=0):" << m_displacement);
401  if (m_displacement) {
402  if (gcp.getDisplacementInputType()) {
403  B2DEBUG(100, "CDCGeometryPar: Read displacement from DB");
404  setDisplacement();
405  } else {
406  readWirePositionParams(c_Base, &geom);
407  }
408  }
409 
410  //Set alignment params. (from input data)
411  m_alignment = CDCGeoControlPar::getInstance().getAlignment();
412  B2DEBUG(100, "CDCGeometryPar: Load alignment params. (=1); not load (=0):" <<
413  m_alignment);
414  if (m_alignment) {
415  if (gcp.getAlignmentInputType()) {
416  B2DEBUG(100, "CDCGeometryPar: Read alignment from DB");
417  setWirPosAlignParams();
418  } else {
419  readWirePositionParams(c_Aligned, &geom);
420  }
421  }
422 
423  //Set misalignment params. (from input data)
424  m_misalignment = CDCGeoControlPar::getInstance().getMisalignment();
425  B2DEBUG(100, "CDCGeometryPar: Load misalignment params. (=1); not load (=0):" <<
426  m_misalignment);
427  if (m_misalignment) {
428  if (gcp.getMisalignmentInputType()) {
429  B2DEBUG(100, "CDCGeometryPar: Read misalignment from DB");
430  setWirPosMisalignParams();
431  } else {
432  readWirePositionParams(c_Misaligned, &geom);
433  }
434  }
435 
436  // Get control params. for CDC FullSim
437  m_thresholdEnergyDeposit = CDCSimControlPar::getInstance().getThresholdEnergyDeposit();
438  m_minTrackLength = CDCSimControlPar::getInstance().getMinTrackLength();
439  m_wireSag = CDCSimControlPar::getInstance().getWireSag();
440  m_modLeftRightFlag = CDCSimControlPar::getInstance().getModLeftRightFlag();
441  if (m_modLeftRightFlag) {
442  B2FATAL("ModifiedLeftRightFlag = true is disabled for now; need to update a G4-related code in framework...");
443  }
444  //N.B. The following two lines are hard-coded since only =1 are used now.
445  m_xtFileFormat = 1;
446  m_sigmaFileFormat = 1;
447 
448  m_XTetc = true;
449  if (m_XTetc) {
450  if (gcp.getXtInputType()) {
451  B2DEBUG(100, "CDCGeometryPar: Read xt from DB");
452  setXtRel(); //Set xt param. (from DB)
453  } else {
454  readXT(gbxParams); //Read xt params. (from file)
455  }
456 
457  if (gcp.getSigmaInputType()) {
458  B2DEBUG(100, "CDCGeometryPar: Read sigma from DB");
459  setSResol(); //Set sigma param. (from DB)
460  } else {
461  readSigma(gbxParams); //Read sigma params. (from file)
462  }
463 
464  if (gcp.getFFactorInputType()) {
465  B2DEBUG(100, "CDCGeometryPar: Read fudge factors from DB");
466  setFFactor(); //Set fudge factors (from DB)
467  } else {
468  readFFactor(gbxParams); //Read fudge factors (from file)
469  }
470 
471  if (gcp.getPropSpeedInputType()) {
472  B2DEBUG(100, "CDCGeometryPar: Read prop-speed from DB");
473  setPropSpeed(); //Set prop-speed (from DB)
474  } else {
475  readPropSpeed(gbxParams); //Read propagation speed
476  }
477 
478  if (gcp.getT0InputType()) {
479  B2DEBUG(100, "CDCGeometryPar: Read t0 from DB");
480  setT0(); //Set t0 (from DB)
481  } else {
482  readT0(gbxParams); //Read t0 (from file)
483  }
484 
485  if (gcp.getBwInputType()) {
486  B2DEBUG(100, "CDCGeometryPar: Read badwire from DB");
487  setBadWire(); //Set bad-wire (from DB)
488  } else {
489  // readBadWire(gbxParams); //Read bad-wire (from file)
490  B2FATAL("Text file input mode for bdwires is disabled now!");
491  }
492 
493  if (gcp.getChMapInputType()) {
494  B2DEBUG(100, "CDCGeometryPar: Read ch-map from DB");
495  setChMap(); //Set ch-map (from DB)
496  } else {
497  readChMap(); //Read ch-map
498  }
499 
500  if (gcp.getTwInputType()) {
501  B2DEBUG(100, "CDCGeometryPar: Read time-walk from DB");
502  setTW(); //Set time-walk coeffs. (from DB)
503  } else {
504  readTW(gbxParams); //Read time-walk coeffs. (from file)
505  }
506  B2DEBUG(100, "CDCGeometryPar: Time-walk param. mode= " << m_twParamMode);
507 
508  if (gcp.getEDepToADCInputType()) {
509  B2DEBUG(29, "CDCGeometryPar: Read EDepToADC from DB");
510  if ((*m_eDepToADCConversionsFromDB).isValid()) {
511  setEDepToADCConversions(); //Set edep-to-adc (from DB)
512  }
513  } else {
514  readEDepToADC(gbxParams); //Read edep-to-adc params. (from file)
515  }
516  }
517 
518  m_XTetc4Recon = 0;
519  // B2INFO("CDCGeometryPar: Load x-t etc. params. for reconstruction (=1); not load and use the same ones for digitization (=0):" <<
520  // B2INFO("CDCGeometryPar: Use the same x-t etc. for reconstruction as those used for digitization");
521  if (m_XTetc4Recon) {
522  readXT(gbxParams, 1);
523  readSigma(gbxParams, 1);
524  readPropSpeed(gbxParams, 1);
525  readT0(gbxParams, 1);
526  readTW(gbxParams, 1);
527  }
528 
529  //calculate and save shifts in super-layers
530  setShiftInSuperLayer();
531 
532 }
533 
534 /*
535 //TODO: move the following two functions to cdc/utilities <-done
536 // Open a file
537 void CDCGeometryPar::openFile(std::ifstream& ifs, const std::string& fileName0) const
538 {
539  std::string fileName1 = "/data/cdc/" + fileName0;
540  std::string fileName = FileSystem::findFile(fileName1);
541 
542  if (fileName == "") {
543  fileName = FileSystem::findFile(fileName0);
544  }
545 
546  if (fileName == "") {
547  B2FATAL("CDCGeometryPar: " << fileName1 << " not exist!");
548  } else {
549  B2INFO("CDCGeometryPar: open " << fileName1);
550  ifs.open(fileName.c_str());
551  if (!ifs) B2FATAL("CDCGeometryPar: cannot open " << fileName1 << " !");
552  }
553 }
554 // Open a file using boost (to be able to read a gzipped file)
555 void CDCGeometryPar::openFile(boost::iostreams::filtering_istream& ifs, const std::string& fileName0) const
556 {
557  std::string fileName1 = "/data/cdc/" + fileName0;
558  std::string fileName = FileSystem::findFile(fileName1);
559 
560  if (fileName == "") {
561  fileName = FileSystem::findFile(fileName0);
562  }
563 
564  if (fileName == "") {
565  B2FATAL("CDCGeometryPar: " << fileName1 << " not exist!");
566  } else {
567  B2INFO("CDCGeometryPar: open " << fileName1);
568  if ((fileName.rfind(".gz") != string::npos) && (fileName.length() - fileName.rfind(".gz") == 3)) {
569  ifs.push(boost::iostreams::gzip_decompressor());
570  }
571  ifs.push(boost::iostreams::file_source(fileName));
572  if (!ifs) B2FATAL("CDCGeometryPar: cannot open " << fileName1 << " !");
573  }
574 }
575 */
576 
577 // Read displacement or (mis)alignment params.
578 //void CDCGeometryPar::readWirePositionParams(EWirePosition set, const CDCGeometry* geom, const GearDir gbxParams)
579 void CDCGeometryPar::readWirePositionParams(EWirePosition set, const CDCGeometry* geom)
580 {
581 
582  std::string fileName0;
583  CDCGeoControlPar& gcp = CDCGeoControlPar::getInstance();
584  if (geom) {
585  if (set == c_Base) {
586  fileName0 = gcp.getDisplacementFile();
587  } else if (set == c_Misaligned) {
588  fileName0 = gcp.getMisalignmentFile();
589  } else if (set == c_Aligned) {
590  fileName0 = gcp.getAlignmentFile();
591  }
592  } else {
593  if (set == c_Base) {
594  fileName0 = gcp.getDisplacementFile();
595  } else if (set == c_Misaligned) {
596  fileName0 = gcp.getMisalignmentFile();
597  } else if (set == c_Aligned) {
598  fileName0 = gcp.getAlignmentFile();
599  }
600  }
601 
602  // ifstream ifs;
603  // openFile(ifs, fileName0);
604  boost::iostreams::filtering_istream ifs;
605  openFileB(ifs, fileName0);
606 
607  uint iL(0), iC(0);
608  const int np = 3;
609  double back[np], fwrd[np], tension;
610  unsigned nRead = 0;
611 
612  while (true) {
613  ifs >> iL >> iC;
614  for (int i = 0; i < np; ++i) {
615  ifs >> back[i];
616  }
617  for (int i = 0; i < np; ++i) {
618  ifs >> fwrd[i];
619  }
620  // if (set != c_Base) ifs >> tension;
621  ifs >> tension;
622 
623  if (ifs.eof()) break;
624 
625  if (iL < m_firstLayerOffset) {
626  continue;
627  }
628 
629  ++nRead;
630 
631  for (int i = 0; i < np; ++i) {
632  if (set == c_Base) {
633  m_BWirPos[iL][iC][i] += (iL < m_firstLayerOffset) ? 0 : back[i];
634  m_FWirPos[iL][iC][i] += (iL < m_firstLayerOffset) ? 0 : fwrd[i];
635  } else if (set == c_Misaligned) {
636  m_BWirPosMisalign[iL][iC][i] = m_BWirPos[iL][iC][i] + ((iL < m_firstLayerOffset) ? 0 : back[i]);
637  m_FWirPosMisalign[iL][iC][i] = m_FWirPos[iL][iC][i] + ((iL < m_firstLayerOffset) ? 0 : fwrd[i]);
638  } else if (set == c_Aligned) {
639  m_BWirPosAlign[iL][iC][i] = m_BWirPos[iL][iC][i] + ((iL < m_firstLayerOffset) ? 0 : back[i]);
640  m_FWirPosAlign[iL][iC][i] = m_FWirPos[iL][iC][i] + ((iL < m_firstLayerOffset) ? 0 : fwrd[i]);
641  }
642  }
643 
644  // double baseTension = 0.;
645 
646  if (set == c_Base) {
647  m_WireSagCoef[iL][iC] = (iL < m_firstLayerOffset) ? 0 : M_PI * m_senseWireDensity * m_senseWireDiameter * m_senseWireDiameter /
648  (8.*(m_senseWireTension + tension));
649  // std::cout <<"base iL, iC, m_senseWireTension, tension= " << iL <<" " << iC <<" "<< m_senseWireTension <<" "<< tension << std::endl;
650  } else if (set == c_Misaligned) {
651  double baseTension = M_PI * m_senseWireDensity * m_senseWireDiameter * m_senseWireDiameter / (8.* m_WireSagCoef[iL][iC]);
652  m_WireSagCoefMisalign[iL][iC] = (iL < m_firstLayerOffset) ? 0 : M_PI * m_senseWireDensity * m_senseWireDiameter *
653  m_senseWireDiameter / (8.* (baseTension + tension));
654  // std::cout <<"misa iL, iC,basetension, tension= " << iL <<" " << iC <<" "<< baseTension <<" "<< tension << std::endl;
655  } else if (set == c_Aligned) {
656  double baseTension = M_PI * m_senseWireDensity * m_senseWireDiameter * m_senseWireDiameter / (8.* m_WireSagCoef[iL][iC]);
657  m_WireSagCoefAlign[iL][iC] = (iL < m_firstLayerOffset) ? 0 : M_PI * m_senseWireDensity * m_senseWireDiameter *
658  m_senseWireDiameter / (8.*(baseTension + tension));
659  // std::cout <<"algn iL, iC,basetension, tension= " << iL <<" " << iC <<" "<< baseTension <<" "<< tension << std::endl;
660  }
661  // std::cout << "baseTension,tension= " << baseTension <<" "<< tension << std::endl;
662 
663  /*
664  if (m_debug) {
665  std::cout << iL << " " << iC;
666  for (int i = 0; i < np; ++i) cout << " " << back[i];
667  for (int i = 0; i < np; ++i) cout << " " << fwrd[i];
668  std::cout << " " << tension << std::endl;
669  }
670  */
671 
672  }
673 
674  if (nRead != m_nSenseWires) B2FATAL("CDCGeometryPar::readWirePositionParams: #lines read-in (=" << nRead <<
675  ") is inconsistent with total #sense wires (=" << m_nSenseWires << ") !");
676 
677  // ifs.close();
678  boost::iostreams::close(ifs);
679 }
680 
681 
682 // Set alignment wire positions
683 void CDCGeometryPar::setWirPosAlignParams()
684 {
685  // Layer alignment
686  for (unsigned iL = 0; iL < c_maxNSenseLayers; ++iL) {
687 
688  if (iL < m_firstLayerOffset) {
689  continue;
690  }
691 
692  // wire number 511 = no wire
693  auto layerID = WireID(iL, 511);
694 
695  // Alignment parameters for layer iL
696  double d_layerXbwd = (*m_alignmentFromDB)->get(layerID, CDCAlignment::layerX);
697  double d_layerYbwd = (*m_alignmentFromDB)->get(layerID, CDCAlignment::layerY);
698  double d_layerPhiBwd = (*m_alignmentFromDB)->get(layerID, CDCAlignment::layerPhi);
699 
700  double d_layerXfwd = (*m_alignmentFromDB)->get(layerID, CDCAlignment::layerDx) + d_layerXbwd;
701  double d_layerYfwd = (*m_alignmentFromDB)->get(layerID, CDCAlignment::layerDy) + d_layerYbwd;
702  double d_layerPhiFwd = (*m_alignmentFromDB)->get(layerID, CDCAlignment::layerDPhi) + d_layerPhiBwd;
703 
704  for (unsigned iC = 0; iC < m_nWires[iL]; ++iC) {
705  // Positions (nominal+displacement) of wire-ends of wire iC in layer iL
706  double wireXbwd = m_BWirPos[iL][iC][0];
707  double wireYbwd = m_BWirPos[iL][iC][1];
708  double wireZbwd = m_BWirPos[iL][iC][2];
709 
710  double wireXfwd = m_FWirPos[iL][iC][0];
711  double wireYfwd = m_FWirPos[iL][iC][1];
712  double wireZfwd = m_FWirPos[iL][iC][2];
713 
714  // Aligned positions of wire-ends are obtained by rotating "nominal+displacement" positions and shifting them using
715  // common parameters for layer rotation and shifts (at corresponding end-caps)
716  m_BWirPosAlign[iL][iC][0] = d_layerXbwd + cos(d_layerPhiBwd) * wireXbwd + sin(d_layerPhiBwd) * wireYbwd;
717  m_BWirPosAlign[iL][iC][1] = d_layerYbwd - sin(d_layerPhiBwd) * wireXbwd + cos(d_layerPhiBwd) * wireYbwd;
718  m_BWirPosAlign[iL][iC][2] = wireZbwd;
719 
720  m_FWirPosAlign[iL][iC][0] = d_layerXfwd + cos(d_layerPhiFwd) * wireXfwd + sin(d_layerPhiFwd) * wireYfwd;
721  m_FWirPosAlign[iL][iC][1] = d_layerYfwd - sin(d_layerPhiFwd) * wireXfwd + cos(d_layerPhiFwd) * wireYfwd;
722  m_FWirPosAlign[iL][iC][2] = wireZfwd;
723  } //end of cell loop
724  } //end of layer loop
725 
726  const int np = 3;
727  double back[np], fwrd[np];
728 
729  for (unsigned iL = 0; iL < c_maxNSenseLayers; ++iL) {
730 
731  if (iL < m_firstLayerOffset) {
732  continue;
733  }
734 
735  for (unsigned iC = 0; iC < m_nWires[iL]; ++iC) {
736  // std::cout << "iLiC= " << iL <<" "<< iC << std::endl;
737  WireID wire(iL, iC);
738  back[0] = (*m_alignmentFromDB)->get(wire, CDCAlignment::wireBwdX);
739  back[1] = (*m_alignmentFromDB)->get(wire, CDCAlignment::wireBwdY);
740  back[2] = (*m_alignmentFromDB)->get(wire, CDCAlignment::wireBwdZ);
741 
742  fwrd[0] = (*m_alignmentFromDB)->get(wire, CDCAlignment::wireFwdX);
743  fwrd[1] = (*m_alignmentFromDB)->get(wire, CDCAlignment::wireFwdY);
744  fwrd[2] = (*m_alignmentFromDB)->get(wire, CDCAlignment::wireFwdZ);
745 
746  for (int i = 0; i < np; ++i) {
747  // On top of the wire-end positions corrected for layer alignment, we apply possible
748  // fine corrections per wire
749  m_BWirPosAlign[iL][iC][i] += back[i];
750  m_FWirPosAlign[iL][iC][i] += fwrd[i];
751  }
752 
753  // double baseTension = 0.;
754  double baseTension = M_PI * m_senseWireDensity * m_senseWireDiameter * m_senseWireDiameter / (8.* m_WireSagCoef[iL][iC]);
755  double tension = (*m_alignmentFromDB)->get(wire, CDCAlignment::wireTension);
756  // std::cout << back[0] <<" "<< back[1] <<" "<< back[2] <<" "<< fwrd[0] <<" "<< fwrd[1] <<" "<< fwrd[2] <<" "<< tension << std::endl;
757  m_WireSagCoefAlign[iL][iC] = M_PI * m_senseWireDensity *
758  m_senseWireDiameter * m_senseWireDiameter / (8.*(baseTension + tension));
759  // std::cout << "baseTension,tension= " << baseTension <<" "<< tension << std::endl;
760  } //end of layer loop
761  } //end of cell loop
762 }
763 
764 
765 // Set misalignment wire positions
766 //TODO: merge this and setWirPosAlignParam() somehow
767 void CDCGeometryPar::setWirPosMisalignParams()
768 {
769  const int np = 3;
770  double back[np], fwrd[np];
771 
772  for (unsigned iL = 0; iL < c_maxNSenseLayers; ++iL) {
773 
774  if (iL < m_firstLayerOffset) {
775  continue;
776  }
777 
778  for (unsigned iC = 0; iC < m_nWires[iL]; ++iC) {
779  // std::cout << "iLiC= " << iL <<" "<< iC << std::endl;
780  WireID wire(iL, iC);
781  back[0] = (*m_misalignmentFromDB)->get(wire, CDCMisalignment::wireBwdX);
782  back[1] = (*m_misalignmentFromDB)->get(wire, CDCMisalignment::wireBwdY);
783  back[2] = (*m_misalignmentFromDB)->get(wire, CDCMisalignment::wireBwdZ);
784 
785  fwrd[0] = (*m_misalignmentFromDB)->get(wire, CDCMisalignment::wireFwdX);
786  fwrd[1] = (*m_misalignmentFromDB)->get(wire, CDCMisalignment::wireFwdY);
787  fwrd[2] = (*m_misalignmentFromDB)->get(wire, CDCMisalignment::wireFwdZ);
788 
789  for (int i = 0; i < np; ++i) {
790  m_BWirPosMisalign[iL][iC][i] = m_BWirPos[iL][iC][i] + back[i];
791  m_FWirPosMisalign[iL][iC][i] = m_FWirPos[iL][iC][i] + fwrd[i];
792  }
793 
794  // double baseTension = 0.;
795  double baseTension = M_PI * m_senseWireDensity * m_senseWireDiameter * m_senseWireDiameter / (8.* m_WireSagCoef[iL][iC]);
796  double tension = (*m_misalignmentFromDB)->get(wire, CDCMisalignment::wireTension);
797  // std::cout << back[0] <<" "<< back[1] <<" "<< back[2] <<" "<< fwrd[0] <<" "<< fwrd[1] <<" "<< fwrd[2] <<" "<< tension << std::endl;
798  m_WireSagCoefMisalign[iL][iC] = M_PI * m_senseWireDensity *
799  m_senseWireDiameter * m_senseWireDiameter / (8.*(baseTension + tension));
800  // std::cout << "baseTension,tension= " << baseTension <<" "<< tension << std::endl;
801  } //end of layer loop
802  } //end of cell loop
803 }
804 
805 
806 // Read x-t params.
807 void CDCGeometryPar::readXT(const GearDir& gbxParams, const int mode)
808 {
809  if (m_xtFileFormat == 0) {
810  // oldReadXT(gbxParams, mode);
811  } else {
812  newReadXT(gbxParams, mode);
813  }
814 }
815 
816 
817 // Read x-t params. (new)
818 void CDCGeometryPar::newReadXT(const GearDir& gbxParams, const int mode)
819 {
820  m_linearInterpolationOfXT = true; //must be true now
821 
822  std::string fileName0 = CDCGeoControlPar::getInstance().getXtFile();
823  if (mode == 1) {
824  fileName0 = gbxParams.getString("xt4ReconFileName");
825  }
826 
827  boost::iostreams::filtering_istream ifs;
828  openFileB(ifs, fileName0);
829  //TODO: use openFile() in cdc/utilities instead of the following 18 lines <- done
830  /*
831  std::string fileName1 = "/data/cdc/" + fileName0;
832  std::string fileName = FileSystem::findFile(fileName1);
833 
834  if (fileName == "") {
835  fileName = FileSystem::findFile(fileName0);
836  }
837 
838  if (fileName == "") {
839  B2FATAL("CDCGeometryPar: " << fileName1 << " not exist!");
840  } else {
841  B2INFO("CDCGeometryPar: open " << fileName1);
842  if ((fileName.rfind(".gz") != string::npos) && (fileName.length() - fileName.rfind(".gz") == 3)) {
843  ifs.push(boost::iostreams::gzip_decompressor());
844  }
845  ifs.push(boost::iostreams::file_source(fileName));
846  if (!ifs) B2FATAL("CDCGeometryPar: cannot open " << fileName1 << " !");
847  }
848  */
849 
850  //read alpha bin info.
851  unsigned short nAlphaBins = 0;
852  if (ifs >> nAlphaBins) {
853  if (nAlphaBins == 0 || nAlphaBins > c_maxNAlphaPoints) B2FATAL("Fail to read alpha bins !");
854  } else {
855  B2FATAL("Fail to read alpha bins !");
856  }
857  m_nAlphaPoints = nAlphaBins;
858  double alpha0, alpha1, alpha2;
859  for (unsigned short i = 0; i < nAlphaBins; ++i) {
860  ifs >> alpha0 >> alpha1 >> alpha2;
861  m_alphaPoints[i] = alpha2;
862  }
863 
864  //read theta bin info.
865  unsigned short nThetaBins = 0;
866  if (ifs >> nThetaBins) {
867  if (nThetaBins == 0 || nThetaBins > c_maxNThetaPoints) B2FATAL("CDCGeometryPar: fail to read theta bins !");
868  } else {
869  B2FATAL("CDCGeometryPar: fail to read theta bins !");
870  }
871  m_nThetaPoints = nThetaBins;
872  double theta0, theta1, theta2;
873 
874  for (unsigned short i = 0; i < nThetaBins; ++i) {
875  ifs >> theta0 >> theta1 >> theta2;
876  m_thetaPoints[i] = theta2;
877  }
878 
879  short np = 0;
880  unsigned short iCL, iLR;
881  const unsigned short npx = c_nXTParams - 1;
882  double xtc[npx];
883  double theta, alpha, dummy1;
884 
885  ifs >> m_xtParamMode >> np;
886  if (m_xtParamMode < 0 || m_xtParamMode > 3) B2FATAL("CDCGeometryPar: invalid xt-parameterization mode read !");
887 
888  if (np <= 0 || np > npx) B2FATAL("CDCGeometryPar: no. of xt-params. outside limits !");
889 
890  const double epsi = 0.1;
891 
892  while (ifs >> iCL) {
893 
894  if (iCL < m_firstLayerOffset) {
895  continue;
896  }
897 
898  ifs >> theta >> alpha >> dummy1 >> iLR;
899  for (int i = 0; i < np; ++i) {
900  ifs >> xtc[i];
901  }
902 
903  int itheta = -99;
904  for (unsigned short i = 0; i < nThetaBins; ++i) {
905  if (fabs(theta - m_thetaPoints[i]) < epsi) {
906  itheta = i;
907  break;
908  }
909  }
910  if (itheta < 0) B2FATAL("CDCGeometryPar: thetas in xt.dat are inconsistent !");
911 
912  int ialpha = -99;
913  for (unsigned short i = 0; i < nAlphaBins; ++i) {
914  if (fabs(alpha - m_alphaPoints[i]) < epsi) {
915  ialpha = i;
916  break;
917  }
918  }
919  if (ialpha < 0) B2FATAL("CDCGeometryPar: alphas in xt.dat are inconsistent !");
920 
921  for (int i = 0; i < np; ++i) {
922  m_XT[iCL][iLR][ialpha][itheta][i] = xtc[i];
923  }
924 
925  double boundT = xtc[6];
926  if (m_xtParamMode == 1) {
927  m_XT[iCL][iLR][ialpha][itheta][np] = ROOT::Math::Chebyshev5(boundT, xtc[0], xtc[1], xtc[2], xtc[3], xtc[4], xtc[5]);
928  } else {
929  m_XT[iCL][iLR][ialpha][itheta][np] =
930  xtc[0] + boundT
931  * (xtc[1] + boundT
932  * (xtc[2] + boundT
933  * (xtc[3] + boundT
934  * (xtc[4] + boundT
935  * (xtc[5])))));
936  }
937  } //end of while loop
938 
939  // ifs.close();
940  boost::iostreams::close(ifs);
941 
942  //convert unit
943  const double degrad = M_PI / 180.;
944  for (unsigned i = 0; i < nAlphaBins; ++i) {
945  m_alphaPoints[i] *= degrad;
946  }
947  for (unsigned i = 0; i < nThetaBins; ++i) {
948  m_thetaPoints[i] *= degrad;
949  }
950 
951 }
952 
953 
954 // Read space resol. params.
955 void CDCGeometryPar::readSigma(const GearDir& gbxParams, const int mode)
956 {
957  if (m_sigmaFileFormat == 0) {
958  // oldReadSigma(gbxParams, mode);
959  } else {
960  newReadSigma(gbxParams, mode);
961  }
962 }
963 
964 void CDCGeometryPar::newReadSigma(const GearDir& gbxParams, const int mode)
965 {
966  m_linearInterpolationOfSgm = true; //must be true now
967 
968  std::string fileName0 = CDCGeoControlPar::getInstance().getSigmaFile();
969  if (mode == 1) {
970  fileName0 = gbxParams.getString("sigma4ReconFileName");
971  }
972 
973  ifstream ifs;
974  // openFile(ifs, fileName0);
975  openFileA(ifs, fileName0);
976 
977  //read alpha bin info.
978  unsigned short nAlphaBins = 0;
979  if (ifs >> nAlphaBins) {
980  if (nAlphaBins == 0 || nAlphaBins > c_maxNAlphaPoints) B2FATAL("Fail to read alpha bins !");
981  } else {
982  B2FATAL("Fail to read alpha bins !");
983  }
984  m_nAlphaPoints4Sgm = nAlphaBins;
985  // std:: cout << nAlphaBins << std::endl;
986  double alpha0, alpha1, alpha2;
987  for (unsigned short i = 0; i < nAlphaBins; ++i) {
988  ifs >> alpha0 >> alpha1 >> alpha2;
989  m_alphaPoints4Sgm[i] = alpha2;
990  // std:: cout << alpha2 << std::endl;
991  }
992 
993  //read theta bin info.
994  unsigned short nThetaBins = 0;
995  if (ifs >> nThetaBins) {
996  if (nThetaBins == 0 || nThetaBins > c_maxNThetaPoints) B2FATAL("CDCGeometryPar: fail to read theta bins !");
997  } else {
998  B2FATAL("CDCGeometryPar: fail to read theta bins !");
999  }
1000  m_nThetaPoints4Sgm = nThetaBins;
1001  // std:: cout << nThetaBins << std::endl;
1002  double theta0, theta1, theta2;
1003 
1004  for (unsigned short i = 0; i < nThetaBins; ++i) {
1005  ifs >> theta0 >> theta1 >> theta2;
1006  m_thetaPoints4Sgm[i] = theta2;
1007  // std:: cout << theta2 << std::endl;
1008  }
1009 
1010  unsigned short np = 0;
1011  unsigned short iCL, iLR;
1012  double sigma[c_nSigmaParams]; // cppcheck-suppress constVariable
1013  double theta, alpha;
1014 
1015  ifs >> m_sigmaParamMode >> np;
1016  // std:: cout << m_sigmaParamMode <<" "<< np << std::endl;
1017  if (m_sigmaParamMode < 0 || m_sigmaParamMode > 4) B2FATAL("CDCGeometryPar: invalid sigma-parameterization mode read !");
1018 
1019  if (np > c_nSigmaParams) B2FATAL("CDCGeometryPar: no. of sigma-params. outside limits !");
1020 
1021  ifs >> m_maxSpaceResol;
1022 
1023  const double epsi = 0.1;
1024 
1025  while (ifs >> iCL) {
1026 
1027  if (iCL < m_firstLayerOffset) {
1028  continue;
1029  }
1030 
1031  ifs >> theta >> alpha >> iLR;
1032  // std::cout << iCL <<" "<< theta <<" "<< alpha <<" "<< iLR << std::endl;
1033  for (int i = 0; i < np; ++i) {
1034  ifs >> sigma[i];
1035  }
1036 
1037  int itheta = -99;
1038  for (unsigned short i = 0; i < nThetaBins; ++i) {
1039  if (fabs(theta - m_thetaPoints4Sgm[i]) < epsi) {
1040  itheta = i;
1041  break;
1042  }
1043  }
1044  if (itheta < 0) B2FATAL("CDCGeometryPar: thetas in sigma.dat are inconsistent !");
1045 
1046  int ialpha = -99;
1047  for (unsigned short i = 0; i < nAlphaBins; ++i) {
1048  if (fabs(alpha - m_alphaPoints4Sgm[i]) < epsi) {
1049  ialpha = i;
1050  break;
1051  }
1052  }
1053  if (ialpha < 0) B2FATAL("CDCGeometryPar: alphas in sigma.dat are inconsistent !");
1054 
1055  for (int i = 0; i < np; ++i) {
1056  m_Sigma[iCL][iLR][ialpha][itheta][i] = sigma[i];
1057  }
1058  } //end of while loop
1059 
1060  ifs.close();
1061 
1062  //convert unit
1063  const double degrad = M_PI / 180.;
1064  for (unsigned i = 0; i < nAlphaBins; ++i) {
1065  m_alphaPoints4Sgm[i] *= degrad;
1066  }
1067  for (unsigned i = 0; i < nThetaBins; ++i) {
1068  m_thetaPoints4Sgm[i] *= degrad;
1069  }
1070 
1071  // std::cout << "end of newreadsigma " << std::endl;
1072 }
1073 
1074 
1075 // Read fudge factors
1076 void CDCGeometryPar::readFFactor(const GearDir& gbxParams, const int mode)
1077 {
1078  std::string fileName0 = CDCGeoControlPar::getInstance().getFFactorFile();
1079  if (mode == 1) {
1080  fileName0 = gbxParams.getString("fudgeFactorFileName");
1081  }
1082  B2WARNING("readFFactor is not ready! " << fileName0);
1083  //TODO; implement the following part.
1084 }
1085 
1086 
1087 // Read propagation speed param.
1088 void CDCGeometryPar::readPropSpeed(const GearDir& gbxParams, const int mode)
1089 {
1090  std::string fileName0 = CDCGeoControlPar::getInstance().getPropSpeedFile();
1091  if (mode == 1) {
1092  fileName0 = gbxParams.getString("propSpeed4ReconFileName");
1093  }
1094 
1095  ifstream ifs;
1096  // openFile(ifs, fileName0);
1097  openFileA(ifs, fileName0);
1098 
1099  uint iL;
1100  double speed;
1101  unsigned nRead = 0;
1102 
1103  while (true) {
1104  ifs >> iL >> speed;
1105  if (ifs.eof()) break;
1106 
1107  ++nRead;
1108 
1109  m_propSpeedInv[iL] = (iL < m_firstLayerOffset) ? 0 : 1. / speed;
1110 
1111  if (m_debug) B2DEBUG(150, iL << " " << speed);
1112  }
1113 
1114  if (nRead != c_maxNSenseLayers) B2FATAL("CDCGeometryPar::readPropSpeed: #lines read-in (=" << nRead <<
1115  ") is inconsistent with total #layers (=" << c_maxNSenseLayers << ") !");
1116 
1117  ifs.close();
1118 }
1119 
1120 /*
1121 // Read deltaz params.
1122 void CDCGeometryPar::readDeltaz(const GearDir gbxParams)
1123 {
1124  std::string fileName0 = gbxParams.getString("deltazFileName");
1125  fileName0 = "/data/cdc/" + fileName0;
1126  std::string fileName = FileSystem::findFile(fileName0);
1127 
1128  ifstream ifs;
1129 
1130  if (fileName == "") {
1131  B2FATAL("CDCGeometryPar: " << fileName0 << " not exist!");
1132  } else {
1133  B2INFO("CDCGeometryPar: " << fileName0 << " exists.");
1134  ifs.open(fileName.c_str());
1135  if (!ifs) B2FATAL("CDCGeometryPar: cannot open " << fileName0 << " !");
1136  }
1137 
1138  int iL;
1139  unsigned nRead = 0;
1140 
1141  while (ifs >> iL) {
1142  ifs >> m_bwdDz[iL] >> m_fwdDz[iL];
1143  ++nRead;
1144  if (m_debug) cout << iL << " " << m_bwdDz[iL] << " " << m_fwdDz[iL] << endl;
1145  }
1146 
1147  if (nRead != c_maxNSenseLayers) B2FATAL("CDCGeometryPar::readDeltaz: #lines read-in (=" << nRead <<
1148  ") is inconsistent with total #layers (=" << c_maxNSenseLayers << ") !");
1149 
1150  ifs.close();
1151 }
1152 */
1153 
1154 
1155 // Read t0 params.
1156 void CDCGeometryPar::readT0(const GearDir& gbxParams, int mode)
1157 {
1158  std::string fileName0 = CDCGeoControlPar::getInstance().getT0File();
1159  if (mode == 1) {
1160  fileName0 = gbxParams.getString("t04ReconFileName");
1161  }
1162 
1163  ifstream ifs;
1164  // openFile(ifs, fileName0);
1165  openFileA(ifs, fileName0);
1166 
1167  uint iL(0), iC(0);
1168  float t0(0);
1169  unsigned nRead = 0;
1170 
1171  while (true) {
1172  ifs >> iL >> iC >> t0;
1173 
1174  if (iL < m_firstLayerOffset) {
1175  continue;
1176  }
1177 
1178  if (ifs.eof()) break;
1179 
1180  ++nRead;
1181 
1182  m_t0[iL][iC] = (iL < m_firstLayerOffset) ? 0. : t0;
1183 
1184  if (m_debug) {
1185  B2DEBUG(150, iL << " " << iC << " " << t0);
1186  }
1187  }
1188 
1189  if (nRead != m_nSenseWires) B2FATAL("CDCGeometryPar::readT0: #lines read-in (=" << nRead <<
1190  ") is inconsistent with total #sense wires (=" << m_nSenseWires << ") !");
1191 
1192  ifs.close();
1193 
1194  calcMeanT0();
1195 }
1196 
1197 
1198 /*
1199 // Read bad-wires.
1200 void CDCGeometryPar::readBadWire(const GearDir gbxParams, int mode)
1201 {
1202  std::string fileName0 = CDCGeoControlPar::getInstance().getBwFile();
1203  if (mode == 1) {
1204  fileName0 = gbxParams.getString("bw4ReconFileName");
1205  }
1206 
1207  ifstream ifs;
1208  // openFile(ifs, fileName0);
1209  openFileA(ifs, fileName0);
1210 
1211  int iCL(0), iW(0);
1212  unsigned nRead = 0;
1213 
1214  while (true) {
1215  ifs >> iCL >> iW;
1216 
1217  if (ifs.eof()) break;
1218 
1219  ++nRead;
1220 
1221  m_badWire.push_back(WireID(iCL, iW));
1222 
1223  if (m_debug) {
1224  B2DEBUG(150, iCL << " " << iW);
1225  }
1226  }
1227 
1228  if (nRead > m_nSenseWires) B2FATAL("CDCGeometryPar::readBadWire: #lines read-in (=" << nRead <<
1229  ") is larger than the total #sense wires (=" << m_nSenseWires << ") !");
1230 
1231  ifs.close();
1232 }
1233 */
1234 
1235 
1236 // Read time-walk parameters
1237 void CDCGeometryPar::readTW(const GearDir& gbxParams, const int mode)
1238 {
1239  std::string fileName0 = CDCGeoControlPar::getInstance().getTwFile();
1240  if (mode == 1) {
1241  fileName0 = gbxParams.getString("tw4ReconFileName");
1242  }
1243 
1244  ifstream ifs;
1245  // openFile(ifs, fileName0);
1246  openFileA(ifs, fileName0);
1247 
1248  unsigned short nPars(0);
1249  ifs >> m_twParamMode >> nPars;
1250  if (m_twParamMode > 1) {
1251  B2FATAL("CDCGeometryPar::readTW: invalid mode specified!");
1252  }
1253  if (nPars > 2) {
1254  B2FATAL("CDCGeometryPar::readTW: invalid #params specified!");
1255  }
1256 
1257  unsigned iBoard = 0;
1258  unsigned nRead = 0;
1259  // Read board id and coefficients
1260  while (ifs >> iBoard) {
1261  for (unsigned short i = 0; i < nPars; ++i) {
1262  ifs >> m_timeWalkCoef[iBoard][i];
1263  }
1264  ++nRead;
1265  }
1266 
1267  if (nRead != c_nBoards) B2FATAL("CDCGeometryPar::readTW: #lines read-in (=" << nRead << ") is inconsistent with #boards (=" <<
1268  c_nBoards
1269  << ") !");
1270 
1271  ifs.close();
1272 }
1273 
1274 
1275 // Read ch-map
1276 //void CDCGeometryPar::readChMap(const GearDir gbxParams)
1277 void CDCGeometryPar::readChMap()
1278 {
1279  std::string fileName0 = CDCGeoControlPar::getInstance().getChMapFile();
1280 
1281  ifstream ifs;
1282  // openFile(ifs, fileName0);
1283  openFileA(ifs, fileName0);
1284 
1285  unsigned short iSL, iL, iW, iB, iC;
1286  unsigned nRead = 0;
1287 
1288  while (true) {
1289  // Read a relation
1290  ifs >> iSL >> iL >> iW >> iB >> iC;
1291  if (ifs.eof()) break;
1292  if (iSL >= c_nSuperLayers or iSL < m_firstSuperLayerOffset) continue;
1293 
1294  ++nRead;
1295  WireID wID(iSL, iL, iW);
1296  m_wireToBoard.insert(pair<WireID, unsigned short>(wID, iB));
1297  }
1298 
1299  if (nRead != m_nSenseWires) B2FATAL("CDCGeometryPar::readChMap: #lines read-in (=" << nRead <<
1300  ") is inconsistent with #sense-wires (="
1301  << m_nSenseWires << ") !");
1302 
1303  ifs.close();
1304 }
1305 
1306 
1307 // Read edep-to-adc
1308 void CDCGeometryPar::readEDepToADC(const GearDir& gbxParams, const int mode)
1309 {
1310  // B2WARNING("CDCGeometryPar: readEDepToADC is not ready!");
1311  std::string fileName0 = CDCGeoControlPar::getInstance().getEDepToADCFile();
1312  if (mode == 1) {
1313  fileName0 = gbxParams.getString("fudgeFactorFileName");
1314  }
1315 
1316  ifstream ifs;
1317  // openFileA(ifs, fileName0);
1318  std::string fileName1 = "/data/cdc/" + fileName0;
1319  std::string fileName = FileSystem::findFile(fileName1, true);
1320 
1321  if (fileName == "") {
1322  fileName = FileSystem::findFile(fileName0, true);
1323  }
1324 
1325  if (fileName == "") {
1326  B2FATAL("CDC::openFile: " << fileName0 << " not exist!");
1327  } else {
1328  // B2INFO("CDC::openFile: open " << fileName);
1329  B2DEBUG(29, "CDC::openFile: open " << fileName);
1330  ifs.open(fileName.c_str());
1331  if (!ifs) B2FATAL("CDC::openFile: cannot open " << fileName << " !");
1332  }
1333 
1334  unsigned short paramMode(0), nParams(0);
1335  ifs >> paramMode >> nParams;
1336  if (paramMode > 1) B2FATAL("Param mode > 1!");
1337  if (nParams > 7) B2FATAL("No. of params. > 7!");
1338  unsigned short groupId(0);
1339  ifs >> groupId;
1340  B2DEBUG(29, paramMode << " " << nParams << " " << groupId);
1341  if (groupId > 0) B2FATAL("GgroupId > 0!");
1342 
1343 
1344  unsigned short cLMin[c_nSuperLayers], cLMax[c_nSuperLayers]; //min and max clayer per super-layer
1345  cLMin[0] = 0;
1346  cLMax[0] = 7;
1347  for (unsigned int sl = 1; sl < c_nSuperLayers; ++sl) {
1348  cLMin[sl] = cLMax[0] + 6 * sl - 5;
1349  cLMax[sl] = cLMax[0] + 6 * sl;
1350  }
1351 
1352  unsigned short id = 0;
1353  double coef = 0.;
1354  unsigned short nRead = 0;
1355  while (ifs >> id) {
1356  for (unsigned short i = 0; i < nParams; ++i) {
1357  ifs >> coef;
1358  for (unsigned short cL = cLMin[id]; cL <= cLMax[id]; ++cL) { //clayer loop
1359  for (unsigned short cell = 0; cell < m_nWires[cL]; ++cell) { //cell loop
1360  m_eDepToADCParams[cL][cell][i] = (cL < m_firstLayerOffset) ? 0 : coef;
1361  // B2DEBUG(29, "cL,cell,i,coef= "<< cL <<" "<< cell <<" "<< i <<" "<< coef);
1362  }
1363  }
1364  }
1365  ++nRead;
1366  if (nRead > c_nSuperLayers) B2FATAL("No. of read in lines > " << c_nSuperLayers << " !");
1367  }
1368 
1369  ifs.close();
1370 }
1371 
1372 
1373 // Set t0 (from DB)
1374 void CDCGeometryPar::setT0()
1375 {
1376  for (unsigned short iCL = 0; iCL < c_maxNSenseLayers; ++iCL) {
1377  for (unsigned short iW = 0; iW < c_maxNDriftCells; ++iW) {
1378  m_t0[iCL][iW] = 0.;
1379  }
1380  }
1381 
1382  for (auto const& ent : (*m_t0FromDB)->getT0s()) {
1383  const WireID wid = WireID(ent.first);
1384  const unsigned short iCL = wid.getICLayer();
1385  const unsigned short iW = wid.getIWire();
1386  m_t0[iCL][iW] = (iCL < m_firstLayerOffset) ? 0. : ent.second;
1387  }
1388 
1389  calcMeanT0();
1390 }
1391 
1392 
1393 // Calculate mean t0
1394 void CDCGeometryPar::calcMeanT0(double minT0, double maxT0, int maxIt, double nStdv, double epsi)
1395 {
1396  double oldMeanT0 = 0;
1397  unsigned short it1 = 0;
1398  for (unsigned short it = 0; it < maxIt; ++it) {
1399  it1 = it;
1400  double effiSum = 0.;
1401  m_meanT0 = 0.;
1402  double stdvT0 = 0;
1403  for (unsigned short iCL = 0; iCL < c_maxNSenseLayers; ++iCL) {
1404  for (unsigned short iW = 0; iW < m_nWires[iCL]; ++iW) {
1405  if (m_t0[iCL][iW] < minT0 || m_t0[iCL][iW] > maxT0) continue;
1406  const WireID wid = WireID(iCL, iW);
1407  if (isHotWire(wid)) continue;
1408  if (isBadWire(wid)) continue;
1409  double effi = 1.;
1410  isDeadWire(wid, effi);
1411  effiSum += effi;
1412  m_meanT0 += (iCL < m_firstLayerOffset) ? 0. : effi * m_t0[iCL][iW];
1413  stdvT0 += (iCL < m_firstLayerOffset) ? 0. : effi * m_t0[iCL][iW] * m_t0[iCL][iW];
1414  }
1415  }
1416  if (effiSum > 0.) {
1417  m_meanT0 /= effiSum;
1418  stdvT0 /= effiSum;
1419  stdvT0 = sqrt(fabs(stdvT0 - m_meanT0 * m_meanT0));
1420  B2DEBUG(29, it << " " << effiSum << " " << m_meanT0 << " " << stdvT0);
1421  if (fabs(m_meanT0 - oldMeanT0) < epsi) break;
1422  oldMeanT0 = m_meanT0;
1423  minT0 = m_meanT0 - nStdv * stdvT0;
1424  maxT0 = m_meanT0 + nStdv * stdvT0;
1425  } else {
1426  B2FATAL("Wire efficiency sum <= 0!");
1427  }
1428  }
1429  if (it1 == maxIt - 1) B2WARNING("Max. iterations(=" << maxIt << ") needed to calculte the mean t0. Strange.");
1430 }
1431 
1432 
1433 // Set bad-wire (from DB)
1434 void CDCGeometryPar::setBadWire()
1435 {
1436  // m_badWire = (*m_badWireFromDB)->getWires();
1437  calcMeanT0();
1438 }
1439 
1440 
1441 // Set prop.-speed (from DB)
1442 void CDCGeometryPar::setPropSpeed()
1443 {
1444  for (unsigned short iCL = 0; iCL < (*m_propSpeedFromDB)->getEntries(); ++iCL) {
1445  m_propSpeedInv[iCL] = (iCL < m_firstLayerOffset) ? 0. : 1. / (*m_propSpeedFromDB)->getSpeed(iCL);
1446  }
1447 }
1448 
1449 
1450 // Set time-walk coefficient (from DB)
1451 void CDCGeometryPar::setTW()
1452 {
1453  // (*m_timeWalkFromDB)->dump();
1454  m_twParamMode = (*m_timeWalkFromDB)->getTwParamMode();
1455 
1456  for (unsigned short iBd = 0; iBd < (*m_timeWalkFromDB)->getEntries(); ++iBd) {
1457  int np = ((*m_timeWalkFromDB)->getTimeWalkParams(iBd)).size();
1458  for (int i = 0; i < np; ++i) {
1459  m_timeWalkCoef[iBd][i] = ((*m_timeWalkFromDB)->getTimeWalkParams(iBd))[i];
1460  }
1461  }
1462 }
1463 
1464 
1465 // Set xt params. (from DB)
1466 void CDCGeometryPar::setXtRel()
1467 {
1468  m_linearInterpolationOfXT = true; //must be true now
1469 
1470  // std::cout <<"setXtRelation called" << std::endl;
1471  m_nAlphaPoints = (*m_xtRelFromDB)->getNoOfAlphaBins();
1472  for (unsigned short i = 0; i < m_nAlphaPoints; ++i) {
1473  m_alphaPoints[i] = (*m_xtRelFromDB)->getAlphaPoint(i);
1474  // std::cout << m_alphaPoints[i]*180./M_PI << std::endl;
1475  }
1476 
1477  m_nThetaPoints = (*m_xtRelFromDB)->getNoOfThetaBins();
1478  for (unsigned short i = 0; i < m_nThetaPoints; ++i) {
1479  m_thetaPoints[i] = (*m_xtRelFromDB)->getThetaPoint(i);
1480  // std::cout << m_thetaPoints[i]*180./M_PI << std::endl;
1481  }
1482 
1483  m_xtParamMode = (*m_xtRelFromDB)->getXtParamMode();
1484 
1485  for (unsigned short iCL = 0; iCL < c_maxNSenseLayers; ++iCL) {
1486  if (iCL < m_firstLayerOffset) {
1487  // m_XT is initialized to 0, but reading
1488  // (*m_xtRelFromDB)->getXtParams(iCL, iLR, iA, iT)
1489  // could fail if iCL < m_firstLayerOffset, thus continue as m_XT would be set to 0 in this case anyway
1490  continue;
1491  }
1492  for (unsigned short iLR = 0; iLR < 2; ++iLR) {
1493  for (unsigned short iA = 0; iA < m_nAlphaPoints; ++iA) {
1494  for (unsigned short iT = 0; iT < m_nThetaPoints; ++iT) {
1495  const std::vector<float> params = (*m_xtRelFromDB)->getXtParams(iCL, iLR, iA, iT);
1496  unsigned short np = params.size();
1497  // std::cout <<"np4xt= " << np << std::endl;
1498  for (unsigned short i = 0; i < np; ++i) {
1499  m_XT[iCL][iLR][iA][iT][i] = params[i];
1500  }
1501 
1502  double boundT = m_XT[iCL][iLR][iA][iT][6];
1503  if (m_xtParamMode == 1) {
1504  m_XT[iCL][iLR][iA][iT][np] = ROOT::Math::Chebyshev5(boundT, m_XT[iCL][iLR][iA][iT][0], m_XT[iCL][iLR][iA][iT][1],
1505  m_XT[iCL][iLR][iA][iT][2], m_XT[iCL][iLR][iA][iT][3], m_XT[iCL][iLR][iA][iT][4], m_XT[iCL][iLR][iA][iT][5]);
1506  } else {
1507  m_XT[iCL][iLR][iA][iT][np] =
1508  m_XT[iCL][iLR][iA][iT][0] + boundT
1509  * (m_XT[iCL][iLR][iA][iT][1] + boundT
1510  * (m_XT[iCL][iLR][iA][iT][2] + boundT
1511  * (m_XT[iCL][iLR][iA][iT][3] + boundT
1512  * (m_XT[iCL][iLR][iA][iT][4] + boundT
1513  * (m_XT[iCL][iLR][iA][iT][5])))));
1514  }
1515  }
1516  }
1517  }
1518  }
1519 
1520 }
1521 
1522 
1523 // Set sigma params. (from DB)
1524 void CDCGeometryPar::setSResol()
1525 {
1526  m_linearInterpolationOfSgm = true; //must be true now
1527 
1528  // std::cout <<"setSResol called" << std::endl;
1529  m_nAlphaPoints4Sgm = (*m_sResolFromDB)->getNoOfAlphaBins();
1530  for (unsigned short i = 0; i < m_nAlphaPoints4Sgm; ++i) {
1531  m_alphaPoints4Sgm[i] = (*m_sResolFromDB)->getAlphaPoint(i);
1532  // std::cout << m_alphaPoints4Sgm[i]*180./M_PI << std::endl;
1533  }
1534 
1535  m_nThetaPoints4Sgm = (*m_sResolFromDB)->getNoOfThetaBins();
1536  for (unsigned short i = 0; i < m_nThetaPoints4Sgm; ++i) {
1537  m_thetaPoints4Sgm[i] = (*m_sResolFromDB)->getThetaPoint(i);
1538  // std::cout << m_thetaPoints4Sgm[i]*180./M_PI << std::endl;
1539  }
1540 
1541  // std::cout << "m_nAlphaPoints4Sgm= " << m_nAlphaPoints4Sgm << std::endl;
1542  // std::cout << "m_nThetaPoints4Sgm= " << m_nThetaPoints4Sgm << std::endl;
1543 
1544  m_sigmaParamMode = (*m_sResolFromDB)->getSigmaParamMode();
1545 
1546  m_maxSpaceResol = (*m_sResolFromDB)->getMaxSpaceResol();
1547 
1548  for (unsigned short iCL = 0; iCL < c_maxNSenseLayers; ++iCL) {
1549  for (unsigned short iLR = 0; iLR < 2; ++iLR) {
1550  for (unsigned short iA = 0; iA < m_nAlphaPoints4Sgm; ++iA) {
1551  for (unsigned short iT = 0; iT < m_nThetaPoints4Sgm; ++iT) {
1552  const std::vector<float> params = (*m_sResolFromDB)->getSigmaParams(iCL, iLR, iA, iT);
1553  unsigned short np = params.size();
1554  // std::cout <<"np4sigma= " << np << std::endl;
1555  for (unsigned short i = 0; i < np; ++i) {
1556  m_Sigma[iCL][iLR][iA][iT][i] = (iCL < m_firstLayerOffset) ? 0. : params[i];
1557  }
1558  }
1559  }
1560  }
1561  }
1562 
1563 }
1564 
1565 
1566 // Set fudge factors (from DB)
1567 void CDCGeometryPar::setFFactor()
1568 {
1569  unsigned short groupId = (*m_fFactorFromDB)->getGroupID();
1570  unsigned short nEnt = (*m_fFactorFromDB)->getEntries();
1571  B2DEBUG(29, "setFFactor called: groupId,nEnt= " << groupId << " " << nEnt);
1572 
1573  if (groupId == 0) { //per all-layers mode
1574  } else {
1575  B2FATAL("CDCGeometryPar:: Invalid group-id " << groupId << " specified!");
1576  }
1577 
1578  for (unsigned short id = 0; id < nEnt; ++id) {
1579  unsigned short np = ((*m_fFactorFromDB)->getFactors(id)).size();
1580  if (np != 3) B2FATAL("CDCGeometryPar:: No. of fudge factors != 3!");
1581  for (unsigned short i = 0; i < np; ++i) {
1582  m_fudgeFactorForSigma[i] = ((*m_fFactorFromDB)->getFactors(id))[i];
1583  B2DEBUG(29, i << " " << m_fudgeFactorForSigma[i]);
1584  }
1585  }
1586 
1587  CDCGeoControlPar& gcp = CDCGeoControlPar::getInstance();
1588  m_fudgeFactorForSigma[0] *= gcp.getAddFudgeFactorForSigmaForData();
1589  m_fudgeFactorForSigma[1] *= gcp.getAddFudgeFactorForSigmaForMC();
1590  B2DEBUG(29, "fudge factors= " << m_fudgeFactorForSigma[0] << " " << m_fudgeFactorForSigma[1] << " " << m_fudgeFactorForSigma[2]);
1591 }
1592 
1593 
1594 // Set ch-map (from DB)
1595 void CDCGeometryPar::setChMap()
1596 {
1597  for (const auto& cm : (*m_chMapFromDB)) {
1598  const unsigned short isl = cm.getISuperLayer();
1599  if (isl >= c_nSuperLayers or isl < m_firstSuperLayerOffset) continue;
1600  const uint il = cm.getILayer();
1601  const int iw = cm.getIWire();
1602  const int iBd = cm.getBoardID();
1603  const WireID wID(isl, il, iw);
1604  m_wireToBoard.insert(pair<WireID, unsigned short>(wID, iBd));
1605  const int iCh = cm.getBoardChannel();
1606  m_wireToChannel.insert(pair<WireID, unsigned short>(wID, iCh));
1607  m_boardAndChannelToWire[iBd][iCh] = wID.getEWire();
1608  }
1609 }
1610 
1611 // Set edep-to-ADC conversion params. (from DB)
1612 void CDCGeometryPar::setEDepToADCConversions()
1613 {
1614  unsigned short groupId = (*m_eDepToADCConversionsFromDB)->getGroupID();
1615  unsigned short nEnt = (*m_eDepToADCConversionsFromDB)->getEntries();
1616  if (groupId == 0) { //per super-layer mode
1617  if (nEnt > c_nSuperLayers) B2FATAL("CDCGeometryPar:: group-id " << groupId << " and #entries " << nEnt << " are inconsistent!");
1618  } else if (groupId == 1) { //per layer mode
1619  if (nEnt > c_maxNSenseLayers) B2FATAL("CDCGeometryPar:: group-id " << groupId << " and #entries " << nEnt << " are inconsistent!");
1620  } else {
1621  B2FATAL("CDCGeometryPar:: Invalid group-id " << groupId << " specified !");
1622  }
1623 
1624  unsigned short cLMin[c_nSuperLayers], cLMax[c_nSuperLayers]; //min and max clayer per super-layer
1625  cLMin[0] = 0;
1626  cLMax[0] = 7;
1627  for (unsigned int sl = 1; sl < c_nSuperLayers; ++sl) {
1628  cLMin[sl] = cLMax[0] + 6 * sl - 5;
1629  cLMax[sl] = cLMax[0] + 6 * sl;
1630  }
1631 
1632  for (unsigned short id = 0; id < nEnt; ++id) {
1633  unsigned short np = ((*m_eDepToADCConversionsFromDB)->getParams(id)).size();
1634  if (np > 7) B2FATAL("CDCGeometryPar:: No. of edep-to-ADC conversion params. > 7");
1635  if (groupId == 0) { //per super-layer; id=super-layer
1636  for (unsigned short cL = cLMin[id]; cL <= cLMax[id]; ++cL) { //clayer loop
1637  for (unsigned short cell = 0; cell < m_nWires[cL]; ++cell) { //cell loop
1638  for (unsigned short i = 0; i < np; ++i) {
1639  m_eDepToADCParams[cL][cell][i] = (cL < m_firstLayerOffset) ? 0. : ((*m_eDepToADCConversionsFromDB)->getParams(id))[i];
1640  }
1641  }
1642  }
1643  } else if (groupId == 1) { //per clayer; id=clayer
1644  for (unsigned short cell = 0; cell < m_nWires[id]; ++cell) { //cell loop
1645  for (unsigned short i = 0; i < np; ++i) {
1646  m_eDepToADCParams[id][cell][i] = (id < m_firstLayerOffset) ? 0. : ((*m_eDepToADCConversionsFromDB)->getParams(id))[i];
1647  }
1648  }
1649  } else if (groupId == 2) { //per wire
1650  //not ready
1651  B2FATAL("CDCGeometryPar::setEDepToADCConversions(): groupId=2 not ready!");
1652  }
1653  }
1654 }
1655 
1656 
1657 double CDCGeometryPar::getEDepToADCConvFactor(unsigned short iCL, unsigned short iW, double edep, double dx, double costh)
1658 {
1659  // double convF = (100.0 / 3.2); //keV -> count
1660  //Model assumed here is from CLEO-c:
1661  //Igen = Imea * [1 + alf*Imea/cth] / [1 + gam*Imea/cth];
1662  //cth = |costh| + dlt;
1663  //Igen: original dE/dx; Imea: measured dE/dx with space-charge effect
1664  const double mainF = (iCL < m_firstLayerOffset) ? 0. : m_eDepToADCParams[iCL][iW][0];
1665  const double& alf = (iCL < m_firstLayerOffset) ? 0. : m_eDepToADCParams[iCL][iW][1];
1666  const double& gam = (iCL < m_firstLayerOffset) ? 0. : m_eDepToADCParams[iCL][iW][2];
1667  const double& dlt = (iCL < m_firstLayerOffset) ? 0. : m_eDepToADCParams[iCL][iW][3];
1668  const double& a = (iCL < m_firstLayerOffset) ? 0. : m_eDepToADCParams[iCL][iW][4];
1669  const double& b = (iCL < m_firstLayerOffset) ? 0. : m_eDepToADCParams[iCL][iW][5];
1670  const double cth = fabs(costh) + dlt;
1671  const double iGen = edep / dx; // keV/cm
1672  const double tmp = cth - gam * iGen;
1673  const double disc = tmp * tmp + 4.*alf * cth * iGen;
1674 
1675  double iMea = 0.;
1676  if (alf == 0.) {
1677  iMea = cth * iGen / tmp;
1678  } else if (disc >= 0.) {
1679  iMea = (-tmp + sqrt(disc)) / (2.*alf);
1680  // if (alf < 0.) {
1681  // B2INFO("alf<0:CHECK");
1682  // B2INFO(-tmp + sqrt(disc)) / (2.*alf));
1683  // B2INFO(-tmp - sqrt(disc)) / (2.*alf));
1684  // }
1685  }
1686 
1687  double convF = mainF;
1688  if (iMea > 0.) {
1689  convF = mainF * std::min(iMea / iGen, 1.);
1690  // if (iMea > iGen) B2DEBUG(29, "iMea > iGen " << iMea <<" "<< iGen);
1691  } else {
1692  //TODO: check the following issue more
1693  // B2WARNING("CDCGeometryPar: Measured dE/dx <= 0!");
1694  // B2DEBUG(29, "CDCGeometryPar: Measured dE/dx <= 0!");
1695  // B2DEBUG(29, "iGen,iMea= " << std::setw(15) << std::scientific << std::setprecision(8) << iGen <<" "<< iMea);
1696  // B2DEBUG(29, "dx,mainF,alf,gam,dlt,cth,tmp,disc= " << dx <<" "<< mainF <<" "<< alf <<" "<< gam <<" "<< dlt <<" "<<" "<< tmp <<" "<< disc);
1697  }
1698  convF *= 1. + a * (costh - b);
1699  return convF;
1700 }
1701 
1702 
1703 void CDCGeometryPar::Print() const
1704 {}
1705 
1706 const B2Vector3D CDCGeometryPar::wireForwardPosition(uint layerID, int cellID, EWirePosition set) const
1707 {
1708  // return early in case of empty layer, i.e. layerID < m_firstLayerOffset
1709  if (layerID < m_firstLayerOffset) {
1710  return B2Vector3D(0, 0, 0);
1711  }
1712 
1713  // std::cout <<"cdcgeopar::fwdpos set= " << set << std::endl;
1714  B2Vector3D wPos(m_FWirPosAlign[layerID][cellID][0],
1715  m_FWirPosAlign[layerID][cellID][1],
1716  m_FWirPosAlign[layerID][cellID][2]);
1717 
1718  if (set == c_Misaligned) {
1719  wPos.SetX(m_FWirPosMisalign[layerID][cellID][0]);
1720  wPos.SetY(m_FWirPosMisalign[layerID][cellID][1]);
1721  wPos.SetZ(m_FWirPosMisalign[layerID][cellID][2]);
1722  } else if (set == c_Base) {
1723  wPos.SetX(m_FWirPos [layerID][cellID][0]);
1724  wPos.SetY(m_FWirPos [layerID][cellID][1]);
1725  wPos.SetZ(m_FWirPos [layerID][cellID][2]);
1726  }
1727 
1728  return wPos;
1729 }
1730 
1731 const B2Vector3D CDCGeometryPar::wireForwardPosition(uint layerID, int cellID, double z, EWirePosition set) const
1732 {
1733  // return early in case of empty layer, i.e. layerID < m_firstLayerOffset
1734  if (layerID < m_firstLayerOffset) {
1735  return B2Vector3D(0, 0, 0);
1736  }
1737 
1738  double yb_sag = 0.;
1739  double yf_sag = 0.;
1740  getWireSagEffect(set, layerID, cellID, z, yb_sag, yf_sag);
1741 
1742  B2Vector3D wPos(m_FWirPosAlign[layerID][cellID][0], yf_sag,
1743  m_FWirPosAlign[layerID][cellID][2]);
1744  if (set == c_Misaligned) {
1745  wPos.SetX(m_FWirPosMisalign[layerID][cellID][0]);
1746  wPos.SetZ(m_FWirPosMisalign[layerID][cellID][2]);
1747  } else if (set == c_Base) {
1748  wPos.SetX(m_FWirPos [layerID][cellID][0]);
1749  wPos.SetZ(m_FWirPos [layerID][cellID][2]);
1750  }
1751 
1752  return wPos;
1753 }
1754 
1755 const B2Vector3D CDCGeometryPar::wireBackwardPosition(uint layerID, int cellID, EWirePosition set) const
1756 {
1757  // return early in case of empty layer, i.e. layerID < m_firstLayerOffset
1758  if (layerID < m_firstLayerOffset) {
1759  return B2Vector3D(0, 0, 0);
1760  }
1761 
1762  B2Vector3D wPos(m_BWirPosAlign[layerID][cellID][0],
1763  m_BWirPosAlign[layerID][cellID][1],
1764  m_BWirPosAlign[layerID][cellID][2]);
1765 
1766  if (set == c_Misaligned) {
1767  wPos.SetX(m_BWirPosMisalign[layerID][cellID][0]);
1768  wPos.SetY(m_BWirPosMisalign[layerID][cellID][1]);
1769  wPos.SetZ(m_BWirPosMisalign[layerID][cellID][2]);
1770  } else if (set == c_Base) {
1771  wPos.SetX(m_BWirPos [layerID][cellID][0]);
1772  wPos.SetY(m_BWirPos [layerID][cellID][1]);
1773  wPos.SetZ(m_BWirPos [layerID][cellID][2]);
1774  }
1775 
1776  return wPos;
1777 }
1778 
1779 const B2Vector3D CDCGeometryPar::wireBackwardPosition(uint layerID, int cellID, double z, EWirePosition set) const
1780 {
1781  // return early in case of empty layer, i.e. layerID < m_firstLayerOffset
1782  if (layerID < m_firstLayerOffset) {
1783  return B2Vector3D(0, 0, 0);
1784  }
1785 
1786  double yb_sag = 0.;
1787  double yf_sag = 0.;
1788  getWireSagEffect(set, layerID, cellID, z, yb_sag, yf_sag);
1789 
1790  B2Vector3D wPos(m_BWirPosAlign[layerID][cellID][0], yb_sag,
1791  m_BWirPosAlign[layerID][cellID][2]);
1792  if (set == c_Misaligned) {
1793  wPos.SetX(m_BWirPosMisalign[layerID][cellID][0]);
1794  wPos.SetZ(m_BWirPosMisalign[layerID][cellID][2]);
1795  } else if (set == c_Base) {
1796  wPos.SetX(m_BWirPos [layerID][cellID][0]);
1797  wPos.SetZ(m_BWirPos [layerID][cellID][2]);
1798  }
1799 
1800  return wPos;
1801 }
1802 
1803 double CDCGeometryPar::getWireSagCoef(EWirePosition set, uint layerID, int cellID) const
1804 {
1805  double coef = m_WireSagCoef[layerID][cellID];
1806  if (set == c_Misaligned) {
1807  coef = m_WireSagCoefMisalign[layerID][cellID];
1808  } else if (set == c_Aligned) {
1809  coef = m_WireSagCoefAlign [layerID][cellID];
1810  }
1811  return coef;
1812 }
1813 
1814 const double* CDCGeometryPar::innerRadiusWireLayer() const
1815 {
1816  static double IRWL[c_maxNSenseLayers] = {0};
1817 
1818  IRWL[0] = outerRadiusInnerWall();
1819  for (unsigned i = 1; i < nWireLayers(); i++)
1820  //IRWL[i] = (m_rSLayer[i - 1] + m_rSLayer[i]) / 2.;
1821  IRWL[i] = (i == m_firstLayerOffset) ? outerRadiusInnerWall() : m_rFLayer[i - 1];
1822 
1823  return IRWL;
1824 }
1825 
1826 const double* CDCGeometryPar::outerRadiusWireLayer() const
1827 {
1828  static double ORWL[c_maxNSenseLayers] = {0};
1829 
1830  ORWL[nWireLayers() - 1] = innerRadiusOuterWall();
1831  for (unsigned i = 0; i < nWireLayers() - 1; i++)
1832  //ORWL[i] = (m_rSLayer[i] + m_rSLayer[i + 1]) / 2.;
1833  ORWL[i] = m_rFLayer[i];
1834 
1835  return ORWL;
1836 }
1837 
1838 unsigned CDCGeometryPar::cellId(unsigned layerId, const B2Vector3D& position) const
1839 {
1840  if (layerId < m_firstLayerOffset) {
1841  return 0;
1842  }
1843 
1844  const unsigned nWires = m_nWires[layerId];
1845 
1846  double offset = m_offSet[layerId];
1847  //...Offset modification to be aligned to axial at z=0...
1848  const double phiSize = 2 * M_PI / double(nWires);
1849  /*{
1850  const double phiF = phiSize * offset
1851  + phiSize * 0.5 * double(m_nShifts[layerId]);
1852  const double phiB = phiSize * offset;
1853  const B2Vector3D f(m_rSLayer[layerId] * cos(phiF), m_rSLayer[layerId] * sin(phiF), m_zSForwardLayer[layerId]);
1854  const B2Vector3D b(m_rSLayer[layerId] * cos(phiB), m_rSLayer[layerId] * sin(phiB), m_zSBackwardLayer[layerId]);
1855 
1856  const B2Vector3D v = f - b;
1857  const B2Vector3D u = v.Unit();
1858  const double beta = (0 - b.Z()) / u.Z();
1859  const B2Vector3D p = b + beta * u;
1860  double phi0 = - atan2(p.Y(), p.X());
1861  offset += phi0 / (2 * M_PI / double(nWires));
1862  }*/
1863 
1864  unsigned j = 0;
1865  for (unsigned i = 0; i < 1; ++i) {
1866  const double phiF = phiSize * (double(i) + offset)
1867  + phiSize * 0.5 * double(m_nShifts[layerId]) + m_globalPhiRotation;
1868  const double phiB = phiSize * (double(i) + offset) + m_globalPhiRotation;
1869  const B2Vector3D f(m_rSLayer[layerId] * cos(phiF), m_rSLayer[layerId] * sin(phiF), m_zSForwardLayer[layerId]);
1870  const B2Vector3D b(m_rSLayer[layerId] * cos(phiB), m_rSLayer[layerId] * sin(phiB), m_zSBackwardLayer[layerId]);
1871  const B2Vector3D v = f - b;
1872  const B2Vector3D u = v.Unit();
1873  const double beta = (position.Z() - b.Z()) / u.Z();
1874  const B2Vector3D p = b + beta * u;
1875  double dPhi = std::atan2(position.Y(), position.X())
1876  - std::atan2(p.Y(), p.X())
1877  + phiSize / 2.;
1878  while (dPhi < 0) dPhi += (2. * M_PI);
1879  j = int(dPhi / phiSize);
1880  while (j >= nWires) j -= nWires;
1881  }
1882 
1883  return j;
1884 }
1885 
1886 void CDCGeometryPar::generateXML(const string& of)
1887 {
1888  //...Open xml file...
1889  std::ofstream ofs(of.c_str(), std::ios::out);
1890  if (! ofs) {
1891  B2ERROR("CDCGeometryPar::read !!! can not open file : "
1892  << of);
1893  }
1894  ofs << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
1895  << endl
1896  << "<Subdetector type=\"CDC\">"
1897  << endl
1898  << " <Name>CDC BelleII </Name>"
1899  << endl
1900  << " <Description>CDC geometry parameters</Description>"
1901  << endl
1902  << " <Version>0</Version>"
1903  << endl
1904  << " <GeoCreator>CDCBelleII</GeoCreator>"
1905  << endl
1906  << " <Content>"
1907  << endl
1908  << " <Rotation desc=\"Rotation of the whole cdc detector (should be the same as beampipe)\" unit=\"mrad\">0.0</Rotation>"
1909  << endl
1910  << " <OffsetZ desc=\"The offset of the whole cdc in z with respect to the IP (should be the same as beampipe)\" unit=\"mm\">0.0</OffsetZ>"
1911  << endl
1912  << " <Material>CDCGas</Material>"
1913  << endl
1914  << endl;
1915 
1916  ofs << " <SLayers>" << endl;
1917 
1918  for (int i = 0; i < m_nSLayer; i++) {
1919  ofs << " <SLayer id=\"" << i << "\">" << endl;
1920  ofs << " <Radius desc=\"Radius of wires in this layer\" unit=\"mm\">" << senseWireR(i) << "</Radius>" << endl;
1921  ofs << " <BackwardZ desc=\"z position of this wire layer at backward endplate\" unit=\"mm\">" << senseWireBZ(
1922  i) << "</BackwardZ>" << endl;
1923  ofs << " <ForwardZ desc=\"z position of this wire layer at forward endplate\" unit=\"mm\">" << senseWireFZ(
1924  i) << "</ForwardZ>" << endl;
1925 // ofs << " <BackwardPhi desc=\"azimuth angle of the first wire in this layer at backward endplate\" unit=\"rad\">" << wireBackwardPosition(i).phi() << "</BackwardPhi>" << endl;
1926 // ofs << " <ForwardPhi desc=\"azimuth angle of the first wire in this layer at forward endplate\" unit=\"rad\">" << wireForwardPosition(i).phi() << "</ForwardPhi>" << endl;
1927  ofs << " <NHoles desc=\"the number of holes in this layer, 2*(cell number)\">" << nWiresInLayer(
1928  i) * 2 << "</NHoles>" << endl;
1929  ofs << " <NShift desc=\"the shifted hole number of each wire in this layer\">" << nShifts(i) << "</NShift>" << endl;
1930  ofs << " <Offset desc=\"wire offset in phi direction at endplate\">" << m_offSet[i] << "</Offset>" << endl;
1931  ofs << " </SLayer>" << endl;
1932  }
1933 
1934  ofs << " </SLayers>" << endl;
1935  ofs << " <FLayers>" << endl;
1936 
1937  for (int i = 0; i < m_nFLayer; i++) {
1938  ofs << " <FLayer id=\"" << i << "\">" << endl;
1939  ofs << " <Radius desc=\"Radius of field wires in this layer\" unit=\"mm\">" << fieldWireR(i) << "</Radius>" << endl;
1940  ofs << " <BackwardZ desc=\"z position of this field wire layer at backward endplate\" unit=\"mm\">" << fieldWireBZ(
1941  i) << "</BackwardZ>" << endl;
1942  ofs << " <ForwardZ desc=\"z position of this field wire layer at forward endplate\" unit=\"mm\">" << fieldWireFZ(
1943  i) << "</ForwardZ>" << endl;
1944  ofs << " </FLayer>" << endl;
1945  }
1946 
1947  ofs << " </FLayers>" << endl;
1948 
1949  ofs << " <InnerWall name=\"InnerWall\">" << endl;
1950  ofs << " <InnerR desc=\"Inner radius\" unit=\"mm\">" << innerRadiusInnerWall() << "</InnerR>" << endl;
1951  ofs << " <OuterR desc=\"Outer radius\" unit=\"mm\">" << outerRadiusInnerWall() << "</OuterR>" << endl;
1952  ofs << " <BackwardZ desc=\"z position at backward endplate\" unit=\"mm\">" << m_zWall[0][0] << "</BackwardZ>" << endl;
1953  ofs << " <ForwardZ desc=\"z position at forward endplate\" unit=\"mm\">" << m_zWall[0][1] << "</ForwardZ>" << endl;
1954  ofs << " </InnerWall>" << endl;
1955 
1956  ofs << " <OuterWall name=\"OuterWall\">" << endl;
1957  ofs << " <InnerR desc=\"Inner radius\" unit=\"mm\">" << innerRadiusOuterWall() << "</InnerR>" << endl;
1958  ofs << " <OuterR desc=\"Outer radius\" unit=\"mm\">" << outerRadiusOuterWall() << "</OuterR>" << endl;
1959  ofs << " <BackwardZ desc=\"z position at backward endplate\" unit=\"mm\">" << m_zWall[2][0] << "</BackwardZ>" << endl;
1960  ofs << " <ForwardZ desc=\"z position at forward endplate\" unit=\"mm\">" << m_zWall[2][1] << "</ForwardZ>" << endl;
1961  ofs << " </OuterWall>" << endl;
1962 
1963  ofs << " </Content>" << endl
1964  << "</Subdetector>" << endl;
1965 }
1966 
1967 void CDCGeometryPar::getWireSagEffect(const EWirePosition set, const unsigned layerID, const unsigned cellID, const double Z,
1968  double& Yb_sag, double& Yf_sag) const
1969 {
1970  //Input
1971  // set : c_Base, c_Misaligned or c_Aligned
1972  // layerID: layer id (0 - 55);
1973  // cellID: cell id in the layer;
1974  // Z: Z-coord. (cm) at which sense wire sag is computed.
1975  //
1976  //Output Yb_sag: Y-corrd. (cm) of intersection of a tangent and the backward endplate.
1977  // Here the tangent is computed from the 1'st derivative of
1978  // a paraboric wire (due to gravity) defined at Z.
1979  // Yf_sag: ibid. but for forward.
1980  //
1981  //N.B.- Maybe replaced with a bit more accurate formula.
1982  // - The electrostatic force effect is not included.
1983 
1984  // return early in case of empty layer, i.e. layerID < m_firstLayerOffset
1985  if (layerID < m_firstLayerOffset) {
1986  Yb_sag = 0.;
1987  Yf_sag = 0.;
1988  return;
1989  }
1990 
1991  double Xb = 0.;
1992  double Xf = 0.;
1993  double Yb = 0.;
1994  double Yf = 0.;
1995  double Zb = 0.;
1996  double Zf = 0.;
1997  double Coef = 0.;
1998 
1999  if (set == c_Aligned) {
2000  Coef = m_WireSagCoefAlign[layerID][cellID];
2001  Yb = m_BWirPosAlign[layerID][cellID][1];
2002  Yf = m_FWirPosAlign[layerID][cellID][1];
2003  if (Coef == 0.) {
2004  Yb_sag = Yb;
2005  Yf_sag = Yf;
2006  return;
2007  }
2008  Xb = m_BWirPosAlign[layerID][cellID][0];
2009  Xf = m_FWirPosAlign[layerID][cellID][0];
2010  Zb = m_BWirPosAlign[layerID][cellID][2];
2011  Zf = m_FWirPosAlign[layerID][cellID][2];
2012 
2013  } else if (set == c_Misaligned) {
2014  Coef = m_WireSagCoefMisalign[layerID][cellID];
2015  Yb = m_BWirPosMisalign[layerID][cellID][1];
2016  Yf = m_FWirPosMisalign[layerID][cellID][1];
2017  if (Coef == 0.) {
2018  Yb_sag = Yb;
2019  Yf_sag = Yf;
2020  return;
2021  }
2022  Xb = m_BWirPosMisalign[layerID][cellID][0];
2023  Xf = m_FWirPosMisalign[layerID][cellID][0];
2024  Zb = m_BWirPosMisalign[layerID][cellID][2];
2025  Zf = m_FWirPosMisalign[layerID][cellID][2];
2026 
2027  } else if (set == c_Base) {
2028  Coef = m_WireSagCoef[layerID][cellID];
2029  Yb = m_BWirPos[layerID][cellID][1];
2030  Yf = m_FWirPos[layerID][cellID][1];
2031  if (Coef == 0.) {
2032  Yb_sag = Yb;
2033  Yf_sag = Yf;
2034  return;
2035  }
2036  Xb = m_BWirPos[layerID][cellID][0];
2037  Xf = m_FWirPos[layerID][cellID][0];
2038  Zb = m_BWirPos[layerID][cellID][2];
2039  Zf = m_FWirPos[layerID][cellID][2];
2040 
2041  } else {
2042  B2FATAL("CDCGeometryPar::getWireSagEffect: called with an invalid set: " << " " << set);
2043  }
2044 
2045  const double dx = Xf - Xb;
2046  const double dy = Yf - Yb;
2047  const double dz = Zf - Zb;
2048 
2049  const double Zfp = sqrt(dz * dz + dx * dx); // Wire length in z-x plane since Zbp==0
2050  const double Zp = (Z - Zb) * Zfp / dz;
2051 
2052  const double Y_sag = (Coef * (Zp - Zfp) + dy / Zfp) * Zp + Yb;
2053  const double dydz = (Coef * (2.*Zp - Zfp) * Zfp + dy) / dz;
2054 
2055  Yb_sag = Y_sag + dydz * (Zb - Z);
2056  Yf_sag = Y_sag + dydz * (Zf - Z);
2057 
2058 }
2059 
2060 void CDCGeometryPar::setDesignWirParam(const unsigned layerID, const unsigned cellID)
2061 {
2062  const unsigned L = layerID;
2063  const unsigned C = cellID;
2064 
2065  const double offset = m_offSet[L];
2066  //...Offset modification to be aligned to axial at z=0...
2067  const double phiSize = 2 * M_PI / double(m_nWires[L]);
2068 
2069  const double phiF = phiSize * (double(C) + offset)
2070  + phiSize * 0.5 * double(m_nShifts[L]) + m_globalPhiRotation;
2071 
2072  m_FWirPos[L][C][0] = (L < m_firstLayerOffset) ? 0. : m_rSLayer[L] * cos(phiF);
2073  m_FWirPos[L][C][1] = (L < m_firstLayerOffset) ? 0. : m_rSLayer[L] * sin(phiF);
2074  m_FWirPos[L][C][2] = (L < m_firstLayerOffset) ? 0. : m_zSForwardLayer[L];
2075 
2076  const double phiB = phiSize * (double(C) + offset) + m_globalPhiRotation;
2077 
2078  m_BWirPos[L][C][0] = (L < m_firstLayerOffset) ? 0. : m_rSLayer[L] * cos(phiB);
2079  m_BWirPos[L][C][1] = (L < m_firstLayerOffset) ? 0. : m_rSLayer[L] * sin(phiB);
2080  m_BWirPos[L][C][2] = (L < m_firstLayerOffset) ? 0. : m_zSBackwardLayer[L];
2081 
2082  for (int i = 0; i < 3; ++i) {
2083  m_FWirPosMisalign[L][C][i] = (L < m_firstLayerOffset) ? 0. : m_FWirPos[L][C][i];
2084  m_BWirPosMisalign[L][C][i] = (L < m_firstLayerOffset) ? 0. : m_BWirPos[L][C][i];
2085  m_FWirPosAlign [L][C][i] = (L < m_firstLayerOffset) ? 0. : m_FWirPos[L][C][i];
2086  m_BWirPosAlign [L][C][i] = (L < m_firstLayerOffset) ? 0. : m_BWirPos[L][C][i];
2087  }
2088 
2089  m_WireSagCoef[L][C] = (L < m_firstLayerOffset) ? 0. : M_PI * m_senseWireDensity * m_senseWireDiameter * m_senseWireDiameter /
2090  (8. * m_senseWireTension);
2091  // m_WireSagCoef [L][C] = 0.;
2092  m_WireSagCoefMisalign[L][C] = (L < m_firstLayerOffset) ? 0. : m_WireSagCoef[L][C];
2093  m_WireSagCoefAlign [L][C] = (L < m_firstLayerOffset) ? 0. : m_WireSagCoef[L][C];
2094 
2095 }
2096 
2097 void CDCGeometryPar::outputDesignWirParam(const unsigned layerID, const unsigned cellID) const
2098 {
2099 
2100  const unsigned L = layerID;
2101  const unsigned C = cellID;
2102 
2103  static bool first = true;
2104  static ofstream ofs;
2105  if (first) {
2106  first = false;
2107  ofs.open("alignment.dat");
2108  }
2109 
2110  ofs << L << " " << C;
2111 
2112  ofs << setiosflags(ios::showpoint | ios::uppercase);
2113 
2114  for (int i = 0; i < 3; ++i) ofs << " " << setw(15) << setprecision(8) << m_BWirPos[L][C][i];
2115 
2116  for (int i = 0; i < 3; ++i) ofs << " " << setw(15) << setprecision(8) << m_FWirPos[L][C][i];
2117  ofs << setiosflags(ios::fixed);
2118  ofs << " " << setw(4) << setprecision(1) << m_senseWireTension;
2119 
2120  ofs << endl;
2121 }
2122 
2123 double CDCGeometryPar::getDriftV(const double time, const unsigned short iCLayer, const unsigned short lr, const double alpha,
2124  const double theta) const
2125 {
2126  if (iCLayer < m_firstLayerOffset) {
2127  return 0.;
2128  }
2129 
2130  double dDdt = 0.;
2131 
2132  //calculate min. drift time
2133  double minTime = getMinDriftTime(iCLayer, lr, alpha, theta);
2134  double delta = time - minTime;
2135 
2136  //convert incoming- to outgoing-lr
2137  unsigned short lro = getOutgoingLR(lr, alpha);
2138 
2139  if (!m_linearInterpolationOfXT) {
2140  B2FATAL("linearInterpolationOfXT = false is not allowed now !");
2141  } else {
2142  double wal(0.);
2143  unsigned short ial[2] = {0};
2144  unsigned short ilr[2] = {lro, lro};
2145  getClosestAlphaPoints(alpha, wal, ial, ilr);
2146  double wth(0.);
2147  unsigned short ith[2] = {0};
2148  getClosestThetaPoints(alpha, theta, wth, ith);
2149 
2150  unsigned short jal(0), jlr(0), jth(0);
2151  double w = 0.;
2152 
2153  //use xt reversed at (x=0,t=tmin) for delta<0 ("negative drifttime")
2154  double timep = delta < 0. ? minTime - delta : time;
2155 
2156  //compute linear interpolation (=weithed average over 4 points) in (alpha-theta) space
2157  for (unsigned k = 0; k < 4; ++k) {
2158  if (k == 0) {
2159  jal = ial[0];
2160  jlr = ilr[0];
2161  jth = ith[0];
2162  w = (1. - wal) * (1. - wth);
2163  } else if (k == 1) {
2164  jal = ial[0];
2165  jlr = ilr[0];
2166  jth = ith[1];
2167  w = (1. - wal) * wth;
2168  } else if (k == 2) {
2169  jal = ial[1];
2170  jlr = ilr[1];
2171  jth = ith[0];
2172  w = wal * (1. - wth);
2173  } else if (k == 3) {
2174  jal = ial[1];
2175  jlr = ilr[1];
2176  jth = ith[1];
2177  w = wal * wth;
2178  }
2179 
2180  double boundary = m_XT[iCLayer][jlr][jal][jth][6];
2181 
2182  if (timep < boundary) {
2183  if (m_xtParamMode == 1) {
2184  const double& c1 = m_XT[iCLayer][jlr][jal][jth][1];
2185  const double& c2 = m_XT[iCLayer][jlr][jal][jth][2];
2186  const double& c3 = m_XT[iCLayer][jlr][jal][jth][3];
2187  const double& c4 = m_XT[iCLayer][jlr][jal][jth][4];
2188  const double& c5 = m_XT[iCLayer][jlr][jal][jth][5];
2189  dDdt += w * ROOT::Math::Chebyshev4(timep, c1 + 3.*c3 + 5.*c5, 4.*c2 + 8.*c4, 6.*c3 + 10.*c5, 8.*c4, 10.*c5);
2190  } else {
2191  dDdt += w * (m_XT[iCLayer][jlr][jal][jth][1] + timep
2192  * (2.*m_XT[iCLayer][jlr][jal][jth][2] + timep
2193  * (3.*m_XT[iCLayer][jlr][jal][jth][3] + timep
2194  * (4.*m_XT[iCLayer][jlr][jal][jth][4] + timep
2195  * (5.*m_XT[iCLayer][jlr][jal][jth][5])))));
2196  }
2197  } else {
2198  dDdt += w * m_XT[iCLayer][jlr][jal][jth][7];
2199  }
2200  } //end of weighted mean loop
2201  }
2202 
2203  dDdt = fabs(dDdt);
2204  //n.b. following line not needed since dDdt > 0 even for delta < 0
2205  // if (delta < 0.) dDdt *= -1.;
2206  return dDdt;
2207 
2208 }
2209 
2210 //TODO: mearge with getDriftLength
2211 double CDCGeometryPar::getDriftLength0(const double time, const unsigned short iCLayer, const unsigned short lr, const double alpha,
2212  const double theta) const
2213 {
2214  if (iCLayer < m_firstLayerOffset) {
2215  return 0.;
2216  }
2217 
2218  double dist = 0.;
2219 
2220  //convert incoming- to outgoing-lr
2221  unsigned short lro = getOutgoingLR(lr, alpha);
2222 
2223  // std::cout << m_linearInterpolationOfXT << std::endl;
2224  // exit(-1);
2225  if (!m_linearInterpolationOfXT) {
2226  B2FATAL("linearInterpolationOfXT = false is not allowed now !");
2227  } else {
2228  double wal(0.);
2229  unsigned short ial[2] = {0};
2230  unsigned short ilr[2] = {lro, lro};
2231  getClosestAlphaPoints(alpha, wal, ial, ilr);
2232  double wth(0.);
2233  unsigned short ith[2] = {0};
2234  getClosestThetaPoints(alpha, theta, wth, ith);
2235 
2236  unsigned short jal(0), jlr(0), jth(0);
2237  double w = 0.;
2238 
2239  //use xt reversed at (x=0,t=tmin) for delta<0 ("negative drifttime")
2240  double timep = time;
2241  // std::cout << "iCLayer,alpha,theta,lro= " << iCLayer <<" "<< (180./M_PI)*alpha <<" "<< (180./M_PI)*theta <<" "<< lro << std::endl;
2242 
2243  //compute linear interpolation (=weithed average over 4 points) in (alpha-theta) space
2244  for (unsigned k = 0; k < 4; ++k) {
2245  if (k == 0) {
2246  jal = ial[0];
2247  jlr = ilr[0];
2248  jth = ith[0];
2249  w = (1. - wal) * (1. - wth);
2250  } else if (k == 1) {
2251  jal = ial[0];
2252  jlr = ilr[0];
2253  jth = ith[1];
2254  w = (1. - wal) * wth;
2255  } else if (k == 2) {
2256  jal = ial[1];
2257  jlr = ilr[1];
2258  jth = ith[0];
2259  w = wal * (1. - wth);
2260  } else if (k == 3) {
2261  jal = ial[1];
2262  jlr = ilr[1];
2263  jth = ith[1];
2264  w = wal * wth;
2265  }
2266 
2267  double boundary = m_XT[iCLayer][jlr][jal][jth][6];
2268 
2269  if (timep < boundary) {
2270  if (m_xtParamMode == 1) {
2271  dist += w * ROOT::Math::Chebyshev5(timep, m_XT[iCLayer][jlr][jal][jth][0], m_XT[iCLayer][jlr][jal][jth][1],
2272  m_XT[iCLayer][jlr][jal][jth][2], m_XT[iCLayer][jlr][jal][jth][3], m_XT[iCLayer][jlr][jal][jth][4], m_XT[iCLayer][jlr][jal][jth][5]);
2273  } else {
2274  dist += w * (m_XT[iCLayer][jlr][jal][jth][0] + timep
2275  * (m_XT[iCLayer][jlr][jal][jth][1] + timep
2276  * (m_XT[iCLayer][jlr][jal][jth][2] + timep
2277  * (m_XT[iCLayer][jlr][jal][jth][3] + timep
2278  * (m_XT[iCLayer][jlr][jal][jth][4] + timep
2279  * (m_XT[iCLayer][jlr][jal][jth][5]))))));
2280  }
2281  } else {
2282  dist += w * (m_XT[iCLayer][jlr][jal][jth][7] * (timep - boundary) + m_XT[iCLayer][jlr][jal][jth][8]);
2283  }
2284  // std::cout <<"k,w,dist= " << k <<" "<< w <<" "<< dist << std::endl;
2285  } //end of weighted mean loop
2286  }
2287 
2288  // dist = fabs(dist);
2289  return dist;
2290 
2291 }
2292 
2293 double CDCGeometryPar::getDriftLength(const double time, const unsigned short iCLayer, const unsigned short lr, const double alpha,
2294  const double theta,
2295  const bool calculateMinTime,
2296  const double inputMinTime) const
2297 {
2298  if (iCLayer < m_firstLayerOffset) {
2299  return 0.;
2300  }
2301 
2302  double dist = 0.;
2303 
2304  //calculate min. drift time
2305  double minTime = calculateMinTime ? getMinDriftTime(iCLayer, lr, alpha, theta) : inputMinTime;
2306  double delta = time - minTime;
2307 
2308  //convert incoming- to outgoing-lr
2309  unsigned short lro = getOutgoingLR(lr, alpha);
2310 
2311  // std::cout << m_linearInterpolationOfXT << std::endl;
2312  // exit(-1);
2313  if (!m_linearInterpolationOfXT) {
2314  B2FATAL("linearInterpolationOfXT = false is not allowed now !");
2315  } else {
2316  double wal(0.);
2317  unsigned short ial[2] = {0};
2318  unsigned short ilr[2] = {lro, lro};
2319  getClosestAlphaPoints(alpha, wal, ial, ilr);
2320  double wth(0.);
2321  unsigned short ith[2] = {0};
2322  getClosestThetaPoints(alpha, theta, wth, ith);
2323 
2324  unsigned short jal(0), jlr(0), jth(0);
2325  double w = 0.;
2326 
2327  //use xt reversed at (x=0,t=tmin) for delta<0 ("negative drifttime")
2328  double timep = delta < 0. ? minTime - delta : time;
2329 
2330  // std::cout << "iCLayer,alpha,theta,lro= " << iCLayer <<" "<< (180./M_PI)*alpha <<" "<< (180./M_PI)*theta <<" "<< lro << std::endl;
2331 
2332  //compute linear interpolation (=weithed average over 4 points) in (alpha-theta) space
2333  for (unsigned k = 0; k < 4; ++k) {
2334  if (k == 0) {
2335  jal = ial[0];
2336  jlr = ilr[0];
2337  jth = ith[0];
2338  w = (1. - wal) * (1. - wth);
2339  } else if (k == 1) {
2340  jal = ial[0];
2341  jlr = ilr[0];
2342  jth = ith[1];
2343  w = (1. - wal) * wth;
2344  } else if (k == 2) {
2345  jal = ial[1];
2346  jlr = ilr[1];
2347  jth = ith[0];
2348  w = wal * (1. - wth);
2349  } else if (k == 3) {
2350  jal = ial[1];
2351  jlr = ilr[1];
2352  jth = ith[1];
2353  w = wal * wth;
2354  }
2355 
2356  // std::cout << "k,w= " << k <<" "<< w << std::endl;
2357  // std::cout << "ial[0],[1],jal,wal= " << ial[0] <<" "<< ial[1] <<" "<< jal <<" "<< wal << std::endl;
2358  // std::cout << "ith[0],[1],jth,wth= " << ith[0] <<" "<< ith[1] <<" "<< jth <<" "<< wth << std::endl;
2359 
2360  /*
2361  std::cout <<"iCLayer= " << iCLayer << std::endl;
2362  std::cout <<"lr= " << lr << std::endl;
2363  std::cout <<"jal,jth= " << jal <<" "<< jth << std::endl;
2364  std::cout <<"wal,wth= " << wal <<" "<< wth << std::endl;
2365  for (int i=0; i<9; ++i) {
2366  std::cout <<"a= "<< i <<" "<< m_XT[iCLayer][lro][jal][jth][i] << std::endl;
2367  }
2368  */
2369  double boundary = m_XT[iCLayer][jlr][jal][jth][6];
2370 
2371  if (timep < boundary) {
2372  if (m_xtParamMode == 1) {
2373  dist += w * ROOT::Math::Chebyshev5(timep, m_XT[iCLayer][jlr][jal][jth][0], m_XT[iCLayer][jlr][jal][jth][1],
2374  m_XT[iCLayer][jlr][jal][jth][2], m_XT[iCLayer][jlr][jal][jth][3], m_XT[iCLayer][jlr][jal][jth][4], m_XT[iCLayer][jlr][jal][jth][5]);
2375  } else {
2376  dist += w * (m_XT[iCLayer][jlr][jal][jth][0] + timep
2377  * (m_XT[iCLayer][jlr][jal][jth][1] + timep
2378  * (m_XT[iCLayer][jlr][jal][jth][2] + timep
2379  * (m_XT[iCLayer][jlr][jal][jth][3] + timep
2380  * (m_XT[iCLayer][jlr][jal][jth][4] + timep
2381  * (m_XT[iCLayer][jlr][jal][jth][5]))))));
2382  }
2383  } else {
2384  dist += w * (m_XT[iCLayer][jlr][jal][jth][7] * (timep - boundary) + m_XT[iCLayer][jlr][jal][jth][8]);
2385  }
2386  // std::cout <<"k,w,dist= " << k <<" "<< w <<" "<< dist << std::endl;
2387  } //end of weighted mean loop
2388  }
2389 
2390  dist = fabs(dist);
2391  if (delta < 0.) dist *= -1.;
2392  return dist;
2393 
2394 }
2395 
2396 double CDCGeometryPar::getMinDriftTime(const unsigned short iCLayer, const unsigned short lr, const double alpha,
2397  const double theta) const
2398 {
2399  if (iCLayer < m_firstLayerOffset) {
2400  return 0.;
2401  }
2402 
2403  double minTime = 0.;
2404 
2405  //convert incoming- to outgoing-lr
2406  unsigned short lro = getOutgoingLR(lr, alpha);
2407 
2408  if (!m_linearInterpolationOfXT) {
2409  B2FATAL("linearInterpolationOfXT = false is not allowed now !");
2410  } else {
2411  double wal(0.);
2412  unsigned short ial[2] = {0};
2413  unsigned short ilr[2] = {lro, lro};
2414  getClosestAlphaPoints(alpha, wal, ial, ilr);
2415  double wth(0.);
2416  unsigned short ith[2] = {0};
2417  getClosestThetaPoints(alpha, theta, wth, ith);
2418 
2419  unsigned short jal(0), jlr(0), jth(0);
2420  double w = 0.;
2421 
2422  double c[6] = {0.}, a[6] = {0.};
2423  for (unsigned k = 0; k < 4; ++k) {
2424  if (k == 0) {
2425  jal = ial[0];
2426  jlr = ilr[0];
2427  jth = ith[0];
2428  w = (1. - wal) * (1. - wth);
2429  } else if (k == 1) {
2430  jal = ial[0];
2431  jlr = ilr[0];
2432  jth = ith[1];
2433  w = (1. - wal) * wth;
2434  } else if (k == 2) {
2435  jal = ial[1];
2436  jlr = ilr[1];
2437  jth = ith[0];
2438  w = wal * (1. - wth);
2439  } else if (k == 3) {
2440  jal = ial[1];
2441  jlr = ilr[1];
2442  jth = ith[1];
2443  w = wal * wth;
2444  }
2445 
2446  for (int i = 0; i < 5; ++i) {
2447  c[i] += w * m_XT[iCLayer][jlr][jal][jth][i];
2448  }
2449  }
2450 
2451  if (m_xtParamMode == 1) { //convert c to coeff for normal-poly if Chebyshev
2452  a[0] = c[0] - c[2] + c[4];
2453  a[1] = c[1] - 3.*c[3] + 5.*c[5];
2454  a[2] = 2.*c[2] - 8.*c[4];
2455  a[3] = 4.*c[3] - 20.*c[5];
2456  a[4] = 8.*c[4];
2457  a[5] = 16.*c[5];
2458  } else { //normal-poly
2459  for (int i = 0; i < 5; ++i) a[i] = c[i];
2460  }
2461 
2462  //estimate an initial value
2463  // bool check = false;
2464  // bool nointersection = false;
2465  if (a[2] != 0.) { //2nd-order approx. near t=0
2466  const double det = a[1] * a[1] - 4.*a[2] * a[0];
2467  if (det >= 0.) {
2468  //Choose the solution with dx/dt > 0 which gives x=0
2469  minTime = (-a[1] + sqrt(det)) / (2.*a[2]);
2470  } else {
2471  //Choose the solution with smallest x
2472  // nointersection = true;
2473  minTime = -a[1] / (2.*a[2]);
2474  // cout <<"smallest-x solution= " << minTime << endl;
2475  }
2476  } else if (a[1] != 0.) {
2477  minTime = -a[0] / a[1]; //1st-order approx.
2478  } else {
2479  B2WARNING("CDCGeometryPar::getMinDriftTime: minDriftTime not determined; assume zero.\n" << "layer(#0-55),lr,alpha(rad),theta= " <<
2480  iCLayer << " " << lr << " " << alpha << " " << theta);
2481  return minTime;
2482  }
2483 
2484  // double minTime0 = minTime;
2485  //higher-order corr. using Newton method; trial to minimize x^2
2486  double edm; // = 10.; //(cm) (SG: fix to avoid cpp-check warning)
2487  // const double epsi4t = 0.01; //(ns)
2488  // const double epsi4x = 1.e-5; //(cm)
2489  const double epsi4x = 5.e-6; //(cm)
2490  // const unsigned short maxIter = 4;
2491  const unsigned short maxIter = 8;
2492  const double maxDt = 20.; //(ns)
2493  unsigned short nIter = 0;
2494  double minXsq = 1.e10; //(cm^2)
2495  double minMinTime = minTime;
2496  // double told = minTime + 1000.*epsi4t;
2497  // while (fabs(minTime - told) > epsi && nIter <= maxIter) {
2498  for (nIter = 0; nIter <= maxIter; ++nIter) {
2499  // told = minTime;
2500  double t = minTime;
2501  double x = a[0] + t * (a[1] + t * (a[2] + t * (a[3] + t * (a[4] + t * a[5]))));
2502  double x2 = x * x;
2503  if (x2 < minXsq) {
2504  minXsq = x2;
2505  minMinTime = t;
2506  }
2507  double xp = a[1] + t * (2 * a[2] + t * (3 * a[3] + t * (4 * a[4] + t * 5 * a[5])));
2508  double xpp = 2 * a[2] + t * (6 * a[3] + t * (12 * a[4] + t * 20 * a[5]));
2509  double den = xp * xp + x * xpp;
2510  if (den <= 0.) {
2511  den = xp * xp;
2512  }
2513 
2514  if (den > 0.) {
2515  //estimated distance to min.
2516  edm = fabs(x * xp) / sqrt(den); //not in distance^2 but in distance
2517  if (edm < epsi4x) break; //converged
2518  }
2519 
2520  double dt = 1.; //dt for den=0 (ns)
2521  if (den != 0.) {
2522  dt = x * xp / den;
2523  if (dt >= 0.) {
2524  dt = std::min(dt, maxDt);
2525  } else {
2526  dt = std::max(dt, -maxDt);
2527  }
2528  } else {
2529  B2WARNING("CDCGeometryPar::getMinDriftTime: den = 0\n" << "layer(#0-55),lr,alpha(rad),theta= " <<
2530  iCLayer << " "
2531  << lr <<
2532  " " << alpha << " " << theta);
2533  }
2534  minTime -= dt;
2535  } //end of iteration loop
2536 
2537  //choose minMinTime for not-converged case
2538  if (nIter == (maxIter + 1)) minTime = minMinTime;
2539 
2540  /*
2541  if (fabs(minTime) > 20.) {
2542  B2WARNING("CDCGeometryPar::getMinDriftTime: |minDriftTime| > 20ns. Ok ?\n" << "layer(#0-55),lr,alpha(rad),theta,minTime(ns)= " <<
2543  iCLayer << " "
2544  << lr <<
2545  " " << alpha << " " << theta << " " << minTime);
2546  }
2547  if (nointersection) {
2548  cout <<"final minTime= " << minTime << endl;
2549  cout <<"final minx = " << a[0] + a[1] * minTime + a[2] *pow(minTime,2) + a[3] *pow(minTime,3) + a[4] *pow(minTime,4) + a[5] *pow(minTime,5) << endl;
2550  }
2551  */
2552  /*
2553  if (check) {
2554  double dmin = 999.;
2555  double tmin = 999.;
2556  for (int i = -10000; i < 10000; ++i) {
2557  double ti = 0.01 * i;
2558  double dl = fabs(getDriftLength0(ti, iCLayer, lr, alpha, theta));
2559  if (dl < dmin) {
2560  dmin = dl;
2561  tmin = ti;
2562  }
2563  }
2564 
2565  double smartd = getDriftLength0(minTime, iCLayer, lr, alpha, theta);
2566  if (check) {
2567  // if (fabs(smartd) > dmin && minTime < tmin && fabs(minTime - tmin) > 0.1) {
2568  B2WARNING("CDCGeometryPar::getMinDriftTime \n" << "layer(#0-55),lr,alpha(rad),theta= " <<
2569  iCLayer << " "
2570  << lr <<
2571  " " << alpha << " " << theta);
2572  B2INFO("det, minTime0= " << det << " " << minTime0);
2573  B2INFO("direct search n,tmin,dmin= " << nIter << " " << tmin << " " << dmin);
2574  B2INFO(" smart search n,tmin,dmin= " << nIter << " " << minTime << " " << getDriftLength0(minTime, iCLayer, lr, alpha, theta));
2575 
2576  for (int i=-200; i < 200; ++i) {
2577  double ti = 0.25*i;
2578  double dl = getDriftLength0(ti, iCLayer, lr, alpha, theta);
2579  std::cout << ti <<" "<< dl << std::endl;
2580  }
2581  exit(-1);
2582  }
2583  }
2584  */
2585  }
2586 
2587  return minTime;
2588 }
2589 
2590 double CDCGeometryPar::getDriftTime(const double dist, const unsigned short iCLayer, const unsigned short lr, const double alpha,
2591  const double theta) const
2592 {
2593  if (iCLayer < m_firstLayerOffset) {
2594  return 0.;
2595  }
2596 
2597  //to be replaced with a smarter algorithm...
2598 
2599  const double eps = 2.5e-1;
2600  const double maxTrials = 100;
2601 
2602  // int ialpha = getAlphaBin(alpha);
2603  // int itheta = getThetaBin(theta);
2604 
2605  //convert incoming- to outgoing-lr
2606  // unsigned short lrp = getOutgoingLR(lr, alpha);
2607 
2608  double maxTime = 2000.; //in ns (n.b. further reduction, 2->1us could be ok)
2609  // if (m_XT[iCLayer][lrp][ialpha][itheta][7] == 0.) {
2610  // maxTime = m_XT[iCLayer][lrp][ialpha][itheta][6];
2611  // }
2612 
2613  double minTime = getMinDriftTime(iCLayer, lr, alpha, theta);
2614  double t0 = minTime;
2615  // std::cout << "minTime,x= " << t0 <<" "<< getDriftLength(t0, iCLayer, lr, alpha, theta) << std::endl;
2616  const bool calMinTime = false;
2617  // double d0 = getDriftLength(t0, iCLayer, lr, alpha, theta, calMinTime, minTime) - dist;
2618  double d0 = - dist;
2619 
2620  unsigned i = 0;
2621  double t1 = maxTime;
2622  double time = dist * m_nominalDriftVInv;
2623  while (((t1 - t0) > eps) && (i < maxTrials)) {
2624  time = 0.5 * (t0 + t1);
2625  double d1 = getDriftLength(time, iCLayer, lr, alpha, theta, calMinTime, minTime) - dist;
2626  // std::cout <<"i,dist,t0,t1,d0,d1= " << i <<" "<< dist <<" "<< t0 <<" "<< t1 <<" "<< d0 <<" "<< d1 << std::endl;
2627  if (d0 * d1 > 0.) {
2628  t0 = time;
2629  } else {
2630  t1 = time;
2631  }
2632  ++i;
2633  }
2634 
2635  if (i >= maxTrials - 1 || time > maxTime) {
2636  B2WARNING("CDCGeometryPar::getDriftTime " << dist << " " << iCLayer << " " << alpha << " " << lr << " " << t0 << " " << t1 << " " <<
2637  time << " " << d0);
2638  }
2639 
2640  // std::cout <<"dist0,dist1= " << dist <<" "<< getDriftLength(time, iCLayer, lr, alpha, theta) <<" "<< getDriftLength(time, iCLayer, lr, alpha, theta) - dist << std::endl;
2641  // std::cout <<"dist0,dist1= " << dist <<" "<< getDriftLength(time, iCLayer, lr, 0., theta) <<" "<< getDriftLength(time, iCLayer, lr, 0., theta) - dist << std::endl;
2642  return time;
2643 
2644 }
2645 
2646 double CDCGeometryPar::getSigma(const double DriftL0, const unsigned short iCLayer, const unsigned short lr, const double alpha,
2647  const double theta) const
2648 {
2649  if (iCLayer < m_firstLayerOffset) {
2650  return 0.;
2651  }
2652 
2653 
2654  double sigma = 0.;
2655  //DriftL0 < 0 for the hit w/driftTime < 0; use |DriftL0| to avoid sigma=nan
2656  const double driftL = fabs(DriftL0);
2657 
2658  //convert incoming- to outgoing-lr
2659  unsigned short lro = getOutgoingLR(lr, alpha);
2660 
2661  if (!m_linearInterpolationOfSgm) {
2662  B2FATAL("linearInterpolationOfSgm = false is not allowed now !");
2663  }
2664  if (m_linearInterpolationOfSgm) {
2665  double wal(0.);
2666  unsigned short ial[2] = {0};
2667  unsigned short ilr[2] = {lro, lro};
2668  getClosestAlphaPoints4Sgm(alpha, wal, ial, ilr);
2669  double wth(0.);
2670  unsigned short ith[2] = {0};
2671  getClosestThetaPoints4Sgm(alpha, theta, wth, ith);
2672 
2673  //compute linear interpolation (=weithed average over 4 points) in (alpha-theta) space
2674  unsigned short jal(0), jlr(0), jth(0);
2675  double w = 0.;
2676  for (unsigned k = 0; k < 4; ++k) {
2677  if (k == 0) {
2678  jal = ial[0];
2679  jlr = ilr[0];
2680  jth = ith[0];
2681  w = (1. - wal) * (1. - wth);
2682  } else if (k == 1) {
2683  jal = ial[0];
2684  jlr = ilr[0];
2685  jth = ith[1];
2686  w = (1. - wal) * wth;
2687  } else if (k == 2) {
2688  jal = ial[1];
2689  jlr = ilr[1];
2690  jth = ith[0];
2691  w = wal * (1. - wth);
2692  } else if (k == 3) {
2693  jal = ial[1];
2694  jlr = ilr[1];
2695  jth = ith[1];
2696  w = wal * wth;
2697  }
2698  // std::cout << "k,w= " << k <<" "<< w << std::endl;
2699  // std::cout << "ial[0],[1],jal,wal= " << ial[0] <<" "<< ial[1] <<" "<< jal <<" "<< wal << std::endl;
2700  // std::cout << "ith[0],[1],jth,wth= " << ith[0] <<" "<< ith[1] <<" "<< jth <<" "<< wth << std::endl;
2701  /*
2702  std::cout <<"iCLayer= " << iCLayer << std::endl;
2703  std::cout <<"lr= " << lr << std::endl;
2704  std::cout <<"jal,jth= " << jal <<" "<< jth << std::endl;
2705  std::cout <<"wal,wth= " << wal <<" "<< wth << std::endl;
2706  for (int i=0; i<9; ++i) {
2707  std::cout <<"a= "<< i <<" "<< m_XT[iCLayer][lro][jal][jth][i] << std::endl;
2708  }
2709  */
2710  const double& P0 = m_Sigma[iCLayer][jlr][jal][jth][0];
2711  const double& P1 = m_Sigma[iCLayer][jlr][jal][jth][1];
2712  const double& P2 = m_Sigma[iCLayer][jlr][jal][jth][2];
2713  const double& P3 = m_Sigma[iCLayer][jlr][jal][jth][3];
2714  const double& P4 = m_Sigma[iCLayer][jlr][jal][jth][4];
2715  const double& P5 = m_Sigma[iCLayer][jlr][jal][jth][5];
2716  const double& P6 = m_Sigma[iCLayer][jlr][jal][jth][6];
2717 
2718 #if defined(CDC_DEBUG)
2719  cout << "driftL= " << driftL << endl;
2720  cout << "iCLayer= " << iCLayer << " " << jlr << " " << jal << " " << jth << endl;
2721  cout << "P0= " << P0 << endl;
2722  cout << "P1= " << P1 << endl;
2723  cout << "P2= " << P2 << endl;
2724  cout << "P3= " << P3 << endl;
2725  cout << "P4= " << P4 << endl;
2726  cout << "P5= " << P5 << endl;
2727  cout << "P6= " << P6 << endl;
2728 #endif
2729  const double P7 = m_sigmaParamMode == 0 ? DBL_MAX : m_Sigma[iCLayer][jlr][jal][jth][7];
2730 
2731  if (driftL < P7) {
2732  sigma += w * sqrt(P0 / (driftL * driftL + P1) + P2 * driftL + P3 +
2733  P4 * exp(P5 * (driftL - P6) * (driftL - P6)));
2734  } else {
2735  double forthTermAtP7 = P4 * exp(P5 * (P7 - P6) * (P7 - P6));
2736  const double& P8 = m_Sigma[iCLayer][jlr][jal][jth][8];
2737  if (m_sigmaParamMode == 1) {
2738  double sigmaAtP7 = sqrt(P0 / (P7 * P7 + P1) + P2 * P7 + P3 + forthTermAtP7);
2739  sigma += w * (P8 * (driftL - P7) + sigmaAtP7);
2740  } else if (m_sigmaParamMode == 2) {
2741  double onePls4AtP7 = sqrt(P0 / (P7 * P7 + P1) + forthTermAtP7);
2742  const double onePls4 = P8 * (driftL - P7) + onePls4AtP7;
2743  sigma += w * sqrt(P2 * driftL + P3 + onePls4 * onePls4);
2744  } else if (m_sigmaParamMode == 3) {
2745  forthTermAtP7 = sqrt(forthTermAtP7);
2746  const double forthTerm = P8 * (driftL - P7) + forthTermAtP7;
2747  sigma += w * sqrt(P0 / (driftL * driftL + P1) + P2 * driftL + P3 +
2748  forthTerm * forthTerm);
2749  } //end of mode
2750  } // end of driftL
2751  } //end of for loop
2752  }
2753 
2754  sigma = std::min(sigma, m_maxSpaceResol);
2755  return sigma;
2756 }
2757 
2758 unsigned short CDCGeometryPar::getOldLeftRight(const B2Vector3D& posOnWire, const B2Vector3D& posOnTrack,
2759  const B2Vector3D& momentum) const
2760 {
2761  unsigned short lr = 0;
2762  double wCrossT = (posOnWire.Cross(posOnTrack)).Z();
2763 
2764  if (wCrossT < 0.) {
2765  lr = 0;
2766  } else if (wCrossT > 0.) {
2767  lr = 1;
2768  } else {
2769  if ((posOnTrack - posOnWire).Perp() != 0.) {
2770  double wCrossP = (posOnWire.Cross(momentum)).Z();
2771  if (wCrossP > 0.) {
2772  if (posOnTrack.Perp() > posOnWire.Perp()) {
2773  lr = 0;
2774  } else {
2775  lr = 1;
2776  }
2777  } else if (wCrossP < 0.) {
2778  if (posOnTrack.Perp() < posOnWire.Perp()) {
2779  lr = 0;
2780  } else {
2781  lr = 1;
2782  }
2783  } else {
2784  lr = 0;
2785  }
2786  } else {
2787  lr = 0;
2788  }
2789  }
2790  return lr;
2791 }
2792 
2793 unsigned short CDCGeometryPar::getNewLeftRightRaw(const B2Vector3D& posOnWire, const B2Vector3D& posOnTrack,
2794  const B2Vector3D& momentum) const
2795 {
2796  const double distanceCrossP = ((posOnWire - posOnTrack).Cross(momentum)).Z();
2797  unsigned short int lr = (distanceCrossP > 0.) ? 1 : 0;
2798  return lr;
2799 }
2800 
2801 //N.B. The following alpha and theta calculations are directly implemented in CDCRecoHit.cc tentatively to avoid a circular dependence betw cdc_dataobjects and cdclib. So be careful when changing the calculations !
2802 double CDCGeometryPar::getAlpha(const B2Vector3D& posOnWire, const B2Vector3D& momentum) const
2803 {
2804  const double wx = posOnWire.X();
2805  const double wy = posOnWire.Y();
2806  const double px = momentum.X();
2807  const double py = momentum.Y();
2808 
2809  const double cross = wx * py - wy * px;
2810  const double dot = wx * px + wy * py;
2811 
2812  return atan2(cross, dot);
2813 }
2814 
2815 double CDCGeometryPar::getTheta(const B2Vector3D& momentum) const
2816 {
2817  return atan2(momentum.Perp(), momentum.Z());
2818 }
2819 
2820 
2821 unsigned short CDCGeometryPar::getOutgoingLR(const unsigned short lr, const double alpha) const
2822 {
2823  unsigned short lro = (fabs(alpha) <= 0.5 * M_PI) ? lr : abs(lr - 1);
2824  return lro;
2825 }
2826 
2827 
2828 double CDCGeometryPar::getOutgoingAlpha(const double alpha) const
2829 {
2830  //convert incoming- to outgoing-alpha
2831  double alphao = alpha;
2832  if (alpha > 0.5 * M_PI) {
2833  alphao -= M_PI;
2834  } else if (alpha < -0.5 * M_PI) {
2835  alphao += M_PI;
2836  }
2837 
2838  return alphao;
2839 }
2840 
2841 double CDCGeometryPar::getOutgoingTheta(const double alpha, const double theta) const
2842 {
2843  //convert incoming- to outgoing-theta
2844  double thetao = fabs(alpha) > 0.5 * M_PI ? M_PI - theta : theta;
2845  // std::cout << alpha <<" "<< thetao << std::endl;
2846  return thetao;
2847 }
2848 
2849 void CDCGeometryPar::getClosestAlphaPoints(const double alpha, double& weight, unsigned short points[2],
2850  unsigned short lrs[2]) const
2851 {
2852  double alphao = getOutgoingAlpha(alpha);
2853  weight = 1.;
2854 
2855  if (alphao < m_alphaPoints[0]) {
2856  points[0] = m_nAlphaPoints - 1;
2857  points[1] = 0;
2858  if (m_nAlphaPoints > 1) {
2859  lrs[0] = abs(lrs[0] - 1); //flip lr
2860  weight = (alphao - (m_alphaPoints[points[0]] - M_PI)) / (m_alphaPoints[points[1]] - (m_alphaPoints[points[0]] - M_PI));
2861  }
2862  } else if (m_alphaPoints[m_nAlphaPoints - 1] <= alphao) {
2863  points[0] = m_nAlphaPoints - 1;
2864  points[1] = 0;
2865  if (m_nAlphaPoints > 1) {
2866  lrs[1] = abs(lrs[1] - 1); //flip lr
2867  weight = (alphao - m_alphaPoints[points[0]]) / (m_alphaPoints[points[1]] + M_PI - m_alphaPoints[points[0]]);
2868  }
2869  } else {
2870  for (unsigned short i = 0; i <= m_nAlphaPoints - 2; ++i) {
2871  if (m_alphaPoints[i] <= alphao && alphao < m_alphaPoints[i + 1]) {
2872  points[0] = i;
2873  points[1] = i + 1;
2874  weight = (alphao - m_alphaPoints[points[0]]) / (m_alphaPoints[points[1]] - m_alphaPoints[points[0]]);
2875  break;
2876  }
2877  }
2878  }
2879  // weight = (alphao - m_alphaPoints[points[0]]) / (m_alphaPoints[points[1]] - m_alphaPoints[points[0]]);
2880 }
2881 
2882 
2883 void CDCGeometryPar::getClosestAlphaPoints4Sgm(const double alpha, double& weight, unsigned short points[2],
2884  unsigned short lrs[2]) const
2885 {
2886  double alphao = getOutgoingAlpha(alpha);
2887  weight = 1.;
2888 
2889  if (alphao < m_alphaPoints4Sgm[0]) {
2890  points[0] = m_nAlphaPoints4Sgm - 1;
2891  points[1] = 0;
2892  if (m_nAlphaPoints4Sgm > 1) {
2893  lrs[0] = abs(lrs[0] - 1); //flip lr
2894  weight = (alphao - (m_alphaPoints4Sgm[points[0]] - M_PI)) / (m_alphaPoints4Sgm[points[1]] - (m_alphaPoints4Sgm[points[0]] - M_PI));
2895  }
2896  } else if (m_alphaPoints4Sgm[m_nAlphaPoints4Sgm - 1] <= alphao) {
2897  points[0] = m_nAlphaPoints4Sgm - 1;
2898  points[1] = 0;
2899  if (m_nAlphaPoints4Sgm > 1) {
2900  lrs[1] = abs(lrs[1] - 1); //flip lr
2901  weight = (alphao - m_alphaPoints4Sgm[points[0]]) / (m_alphaPoints4Sgm[points[1]] + M_PI - m_alphaPoints4Sgm[points[0]]);
2902  }
2903  } else {
2904  for (unsigned short i = 0; i <= m_nAlphaPoints4Sgm - 2; ++i) {
2905  if (m_alphaPoints4Sgm[i] <= alphao && alphao < m_alphaPoints4Sgm[i + 1]) {
2906  points[0] = i;
2907  points[1] = i + 1;
2908  weight = (alphao - m_alphaPoints4Sgm[points[0]]) / (m_alphaPoints4Sgm[points[1]] - m_alphaPoints4Sgm[points[0]]);
2909  break;
2910  }
2911  }
2912  }
2913 }
2914 
2915 
2916 void CDCGeometryPar::getClosestThetaPoints(const double alpha, const double theta, double& weight, unsigned short points[2]) const
2917 {
2918  const double thetao = getOutgoingTheta(alpha, theta);
2919 
2920  if (thetao < m_thetaPoints[0]) {
2921  // points[0] = 0;
2922  // points[1] = 1;
2923  points[0] = 0;
2924  points[1] = 0;
2925  weight = 1.;
2926  } else if (m_thetaPoints[m_nThetaPoints - 1] <= thetao) {
2927  // points[0] = m_nThetaPoints - 2;
2928  // points[1] = m_nThetaPoints - 1;
2929  points[0] = m_nThetaPoints - 1;
2930  points[1] = m_nThetaPoints - 1;
2931  weight = 1.;
2932  } else {
2933  for (unsigned short i = 0; i <= m_nThetaPoints - 2; ++i) {
2934  if (m_thetaPoints[i] <= thetao && thetao < m_thetaPoints[i + 1]) {
2935  points[0] = i;
2936  points[1] = i + 1;
2937  weight = (thetao - m_thetaPoints[points[0]]) / (m_thetaPoints[points[1]] - m_thetaPoints[points[0]]);
2938  break;
2939  }
2940  }
2941  }
2942  // weight = (thetao - m_thetaPoints[points[0]]) / (m_thetaPoints[points[1]] - m_thetaPoints[points[0]]);
2943 }
2944 
2945 
2946 void CDCGeometryPar::getClosestThetaPoints4Sgm(const double alpha, const double theta, double& weight,
2947  unsigned short points[2]) const
2948 {
2949  const double thetao = getOutgoingTheta(alpha, theta);
2950 
2951  if (thetao < m_thetaPoints4Sgm[0]) {
2952  points[0] = 0;
2953  points[1] = 0;
2954  weight = 1.;
2955  } else if (m_thetaPoints4Sgm[m_nThetaPoints4Sgm - 1] <= thetao) {
2956  points[0] = m_nThetaPoints4Sgm - 1;
2957  points[1] = m_nThetaPoints4Sgm - 1;
2958  weight = 1.;
2959  } else {
2960  for (unsigned short i = 0; i <= m_nThetaPoints4Sgm - 2; ++i) {
2961  if (m_thetaPoints4Sgm[i] <= thetao && thetao < m_thetaPoints4Sgm[i + 1]) {
2962  points[0] = i;
2963  points[1] = i + 1;
2964  weight = (thetao - m_thetaPoints4Sgm[points[0]]) / (m_thetaPoints4Sgm[points[1]] - m_thetaPoints4Sgm[points[0]]);
2965  break;
2966  }
2967  }
2968  }
2969 }
2970 
2971 
2972 void CDCGeometryPar::setDisplacement()
2973 {
2974  // std::cout <<"setDisplacement called" << std::endl;
2975  for (const auto& disp : (*m_displacementFromDB)) {
2976  // const int iLayer0 = disp.getICLayer();
2977  // const int iWire0 = disp.getIWire();
2978  const int iLayer = WireID(disp.getEWire()).getICLayer();
2979  const int iWire = WireID(disp.getEWire()).getIWire();
2980  // if (iLayer0 != iLayer) B2FATAL("Layer0 != Layer");
2981  // if (iWire0 != iWire) B2FATAL("Wire0 != Wire");
2982  m_FWirPos[iLayer][iWire][0] += (iLayer < m_firstLayerOffset) ? 0. : disp.getXFwd();
2983  m_FWirPos[iLayer][iWire][1] += (iLayer < m_firstLayerOffset) ? 0. : disp.getYFwd();
2984  m_FWirPos[iLayer][iWire][2] += (iLayer < m_firstLayerOffset) ? 0. : disp.getZFwd();
2985  m_BWirPos[iLayer][iWire][0] += (iLayer < m_firstLayerOffset) ? 0. : disp.getXBwd();
2986  m_BWirPos[iLayer][iWire][1] += (iLayer < m_firstLayerOffset) ? 0. : disp.getYBwd();
2987  m_BWirPos[iLayer][iWire][2] += (iLayer < m_firstLayerOffset) ? 0. : disp.getZBwd();
2988  m_WireSagCoef[iLayer][iWire] = (iLayer < m_firstLayerOffset) ? 0. : M_PI * m_senseWireDensity * m_senseWireDiameter *
2989  m_senseWireDiameter / (8.*
2990  (m_senseWireTension + disp.getTension()));
2991  // std::cout <<"setdisp iL, iC, nominaltension, tension= " << iLayer <<" " << iWire <<" "<< m_senseWireTension <<" "<< disp.getTension() << std::endl;
2992  }
2993 }
2994 
2995 
2996 void CDCGeometryPar::setShiftInSuperLayer()
2997 {
2998  const unsigned short nLayers[c_nSuperLayers] = {8, 6, 6, 6, 6, 6, 6, 6, 6}; //tentaive
2999 
3000  for (unsigned short SLayer = 0; SLayer < c_nSuperLayers; ++SLayer) {
3001  unsigned short firstCLayer = 0;
3002  for (unsigned short i = 0; i < SLayer; ++i) {
3003  firstCLayer += nLayers[i];
3004  }
3005  // std::cout <<"SLayer,firstCLayer= " << SLayer <<" "<< firstCLayer << std::endl;
3006 
3007  B2Vector3D firstBPos = wireBackwardPosition(firstCLayer, 0);
3008  for (unsigned short Layer = 0; Layer < nLayers[SLayer]; ++Layer) {
3009  unsigned short CLayer = firstCLayer + Layer;
3010 
3011  if (CLayer == firstCLayer) {
3012  m_shiftInSuperLayer[SLayer][Layer] = 0;
3013 
3014  } else if (CLayer == firstCLayer + 1) {
3015  B2Vector3D BPos = wireBackwardPosition(CLayer, 0);
3016  m_shiftInSuperLayer[SLayer][Layer] = (BPos.Cross(firstBPos)).Z() > 0. ? -1 : 1;
3017  // std::cout <<"CLayer,Layer,shift= " << CLayer <<" "<< Layer <<" "<< m_shiftInSuperLayer[SLayer][Layer] <<" "<< (BPos.Cross(firstBPos)).Z() << std::endl;
3018 
3019  } else {
3020  if (Layer % 2 == 0) {
3021  m_shiftInSuperLayer[SLayer][Layer] = 0;
3022  } else {
3023  m_shiftInSuperLayer[SLayer][Layer] = m_shiftInSuperLayer[SLayer][1];
3024  }
3025  }
3026  // std::cout <<"CLayer,Layer,shift= " << CLayer <<" "<< Layer <<" "<< m_shiftInSuperLayer[SLayer][Layer] << std::endl;
3027  }
3028  }
3029 }
3030 
3031 signed short CDCGeometryPar::getShiftInSuperLayer(unsigned short iSuperLayer, unsigned short iLayer) const
3032 {
3033  return m_shiftInSuperLayer[iSuperLayer][iLayer];
3034 }
B2Vector3< DataType > Cross(const B2Vector3< DataType > &p) const
Cross product.
Definition: B2Vector3.h:296
DataType Z() const
access variable Z (= .at(2) without boundary check)
Definition: B2Vector3.h:435
void SetX(DataType x)
set X/1st-coordinate
Definition: B2Vector3.h:457
DataType X() const
access variable X (= .at(0) without boundary check)
Definition: B2Vector3.h:431
DataType Y() const
access variable Y (= .at(1) without boundary check)
Definition: B2Vector3.h:433
B2Vector3< DataType > Unit() const
Unit vector parallel to this.
Definition: B2Vector3.h:269
void SetZ(DataType z)
set Z/3rd-coordinate
Definition: B2Vector3.h:461
void SetY(DataType y)
set Y/2nd-coordinate
Definition: B2Vector3.h:459
DataType Perp() const
The transverse component (R in cylindrical coordinate system).
Definition: B2Vector3.h:200
The Class for CDC geometry.
Definition: CDCGeometry.h:27
The Class for CDC Geometry Control Parameters.
bool getSigmaInputType()
Get input type for sigma.
bool getMisalignmentInputType()
Get input type for wire misalignment.
bool getDisplacementInputType()
Get input type for wire displacement.
double getAddFudgeFactorForSigmaForMC() const
Get additional fudge factor for space resol for MC.
std::string getDisplacementFile() const
Get input file name for wire displacement.
std::string getMisalignmentFile() const
Get input file name for wire misalignment.
std::string getAlignmentFile() const
Get input file name for wire alignment.
bool getAlignmentInputType()
Get input type for wire alignment.
bool getT0InputType()
Get input type for t0.
bool getEDepToADCInputType()
Get input type for edeptoadc.
bool getMisalignment() const
Get misalignment switch.
double getAddFudgeFactorForSigmaForData() const
Get additional fudge factor for space resol for data.
bool getTwInputType()
Get input type for time-walk.
bool getChMapInputType()
Get input type for channel map.
bool getFFactorInputType()
Get input type for fuge factor.
bool getXtInputType()
Get input type for xt.
bool getBwInputType()
Get input type for bad wire.
bool getPropSpeedInputType()
Get input type for prop.
The Class for CDC Geometry Parameters.
EWirePosition
Wire position set.
void addCallback(std::function< void(const std::string &)> callback, bool onDestruction=false)
Add a callback method.
Class for accessing arrays of objects in the database.
Definition: DBArray.h:26
Class for accessing objects in the database.
Definition: DBObjPtr.h:21
GearDir is the basic class used for accessing the parameter store.
Definition: GearDir.h:31
virtual std::string getString(const std::string &path="") const noexcept(false) override
Get the parameter path as a string.
Definition: GearDir.h:69
Optional DBObjPtr: This class behaves the same as the DBObjPtr except that it will not raise errors w...
Definition: DBObjPtr.h:48
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 getEWire() const
Getter for encoded wire number.
Definition: WireID.h:154
B2Vector3< double > B2Vector3D
typedef for common usage with double
Definition: B2Vector3.h:516
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
T dot(GeneralVector< T > a, GeneralVector< T > b)
dot product of two general vectors
Definition: beamHelpers.h:163
void openFileB(boost::iostreams::filtering_istream &ifs, const std::string &fileName0)
Open a file using boost (to be able to read a gzipped file)
Definition: OpenFile.cc:45
void openFileA(std::ifstream &ifs, const std::string &fileName0)
Open a file.
Definition: OpenFile.cc:26
Abstract base class for different kinds of events.