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