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