StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StTpcCoordinateTransform.cc
1 /***********************************************************************
2  *
3  * $Id: StTpcCoordinateTransform.cc,v 1.53 2021/05/10 16:46:10 fisyak Exp $
4  *
5  * Author: brian Feb 6, 1998
6  *
7  ***********************************************************************
8  * Description:
9  *
10  * Geometrical transformation Routines for:
11  * Raw Pad Coordinate <--> Local Coordinate
12  * Local Coordinate <--> Global Coordinate
13  *
14  * These Routines deal positions ONLY!
15  *
16  ***********************************************************************
17  *
18  * $Log: StTpcCoordinateTransform.cc,v $
19  * Revision 1.53 2021/05/10 16:46:10 fisyak
20  * Add new scheme: offset = clocks*timebin + t0
21  *
22  * Revision 1.52 2018/12/05 14:56:28 fisyak
23  * Fix a bug with radial row position
24  *
25  * Revision 1.51 2018/12/04 19:38:07 fisyak
26  * Add J.Thomas fix for iTPC survey
27  *
28  * Revision 1.50 2018/10/17 20:45:24 fisyak
29  * Restore update for Run XVIII dE/dx calibration removed by Gene on 08/07/2018
30  *
31  * Revision 1.48 2018/08/07 03:43:37 fisyak
32  * iTPC corrections
33  *
34  * Revision 1.46 2018/06/21 01:46:54 perev
35  * iTPCheckIn
36  *
37  * Revision 1.42.6.3 2018/05/28 23:56:26 perev
38  * Add backward compatibility
39  *
40  * Revision 1.42.6.2 2018/05/02 19:41:33 perev
41  * Supress some Irakli correction
42  *
43  * Revision 1.42 2015/07/19 22:20:42 fisyak
44  * Add recalculation of pad row during transformation
45  *
46  * Revision 1.41 2014/07/01 20:29:02 fisyak
47  * Clean up
48  *
49  * Revision 1.40 2014/06/26 21:29:27 fisyak
50  * New Tpc Alignment, v632
51  *
52  * Revision 1.39 2012/10/23 20:13:17 fisyak
53  * Move xFromPad from h- to cxx-file
54  *
55  * Revision 1.38 2012/09/13 20:57:28 fisyak
56  * Corrections for iTpx
57  *
58  * Revision 1.37 2012/05/07 14:38:41 fisyak
59  * Remvoe hardcoded separation between Inner and Outer Sectors
60  *
61  * Revision 1.36 2011/01/18 14:34:28 fisyak
62  * Clean up TpcDb interfaces and Tpc coordinate transformation
63  *
64  * Revision 1.35 2009/11/02 17:32:25 fisyak
65  * remove defaults in Tpc Coordinate transformations
66  *
67  * Revision 1.34 2009/05/20 02:49:51 genevb
68  * Introduce tpcPadrowT0 time offsets
69  *
70  * Revision 1.33 2009/03/16 14:23:59 fisyak
71  * Use StDetectorDb chairs for TpcGlobalPosition and TpcSectorPosition
72  *
73  * Revision 1.32 2008/12/23 17:27:57 fisyak
74  * Use tpcT0 chair, use sector/row in global => local transformation
75  *
76  * Revision 1.31 2008/06/04 19:18:11 fisyak
77  * Account sector t0 shift only once
78  *
79  * Revision 1.30 2008/05/27 14:26:40 fisyak
80  * Use TChairs, absorb shift tau shift, introduce sector to sector time offset
81  *
82  * Revision 1.29 2007/07/12 19:22:00 fisyak
83  * Tpc Drift Velocity depends on West/East half
84  *
85  * Revision 1.28 2007/05/17 15:28:57 fisyak
86  * Replace cout and cerr with Loggger
87  *
88  * Revision 1.27 2007/03/21 16:39:04 fisyak
89  * TpcCoordinate transformation via TGeoHMatrix
90  *
91  * Revision 1.26 2005/07/06 19:10:34 fisyak
92  * Add TpcCoordinate transormation classes to dictionary, use templated StThreeVector
93  *
94  * Revision 1.25 2004/06/05 23:31:09 fisyak
95  * Add (sector,row) for Tpc Coordinate/Direction transformations; Change sign of t0zoffset correction (to be synch. with fcf)
96  *
97  * Revision 1.24 2004/03/10 20:30:39 fisyak
98  * Comment out check that Z is in fid. volume
99  *
100  * Revision 1.23 2004/03/05 17:22:54 fisyak
101  * Add TPC transformations for direction, aligned sectors, protection in order to stay in the same sector when moving from/to Pad coordinates
102  *
103  * Revision 1.22 2004/01/14 22:39:08 fisyak
104  * unsigned int => size_t to make alpha happy
105  *
106  * Revision 1.21 2001/05/23 00:09:55 hardtke
107  * Add error message if rotation matrix inversion fails
108  *
109  * Revision 1.20 2001/05/22 22:32:14 hardtke
110  * Add tpc global to local transformations
111  *
112  * Revision 1.19 2000/12/05 17:54:23 hardtke
113  * Fix bug in sectorFromCoordinate
114  *
115  * Revision 1.18 2000/06/24 00:20:35 hardtke
116  * remove shaping time from time-to-z conversion
117  *
118  * Revision 1.17 2000/06/06 18:17:49 calderon
119  * change exit to assert
120  *
121  * Revision 1.16 2000/05/31 19:30:38 hardtke
122  * lannys modification to t0 definitions
123  *
124  * Revision 1.15 2000/05/25 20:51:31 hardtke
125  * make z-to-time functions public, use correct t0s, get rid of spurious 0.5
126  *
127  * Revision 1.14 2000/04/17 20:14:42 calderon
128  * fix bug, did not remove all use of matrices in last step of
129  * rotation from local sector -> local.
130  *
131  * Revision 1.13 2000/04/13 22:57:53 calderon
132  * use lookup table of sines and cosines instead of calculating them
133  * each time
134  *
135  * Revision 1.12 2000/04/05 23:00:55 calderon
136  * Use the outer sector edge as the boundary between charge going to
137  * padrow 13 or 14.
138  *
139  * Revision 1.11 2000/04/05 20:00:19 hardtke
140  * check for physical sector number before getting t0 table
141  *
142  * Revision 1.10 2000/04/05 13:58:13 hardtke
143  * correct mistake in drift velocity units
144  *
145  * Revision 1.9 2000/04/04 20:32:27 hardtke
146  * use correct drift velocity from database in time to z conversion
147  *
148  * Revision 1.8 2000/04/03 16:23:51 calderon
149  * Fix bug in rowFromLocal. Boundary btw inner and outer sector is now
150  * taken as midpoint of last inner row (plus half its row pitch) and
151  * first outer row (minus half its row pitch).
152  *
153  * Revision 1.7 2000/03/30 17:03:24 hardtke
154  * add pad-by-pad t0 offsets to z calculation
155  *
156  * Revision 1.6 2000/02/24 18:20:58 hardtke
157  * use drift distance and offsets from the database
158  *
159  * Revision 1.5 2000/02/23 14:52:59 hardtke
160  * fix StTpcLocalSectorCoordinate to StTpcLocalCoordinate conversion
161  *
162  * Revision 1.4 2000/02/10 01:19:37 calderon
163  * Tpc Local Sector Coordinate definitions where
164  * y is up,
165  * z points toward central membrane,
166  * x is such that everything is righthanded
167  * There are still some parameters that need to be taken from
168  * database.
169  *
170  * Revision 1.3 2000/02/02 23:01:38 calderon
171  * Changes for CC5
172  * Tests withs StTpcDb still going.
173  *
174  * Revision 1.2 1999/12/03 00:50:31 calderon
175  * Using StTpcDb (there are still problems with SlowControl parameters).
176  *
177  * Revision 1.1 1999/11/19 19:01:08 calderon
178  * First version of files for StDbUtilities.
179  * Note: this package uses StTpcDb.
180  * There are some parameters
181  * that are not yet kept in StTpcDb. When StTpcDb has them, the code
182  * will be changed to use them from StTpcDb.
183  * There are no Ftpc or Svt Coordinate transformations in here yet.
184  *
185  * Revision 1.14 1999/10/25 18:38:49 calderon
186  * changed mPos and pos() to mPosition and position() to
187  * be compatible with StEvent/StMcEvent.
188  *
189  * Revision 1.13 1999/10/04 15:21:58 long
190  * new coordinate system in the trs
191  *
192  * Revision 1.13 1999/10/01 17:15:00 Hui Long
193  * using new coordinate system proposed by Brian and Thomas
194  * See their proposal for the new definition of the coordinate systems
195  * Revision 1.12 1999/07/19 21:40:13 lasiuk
196  * local->raw transform redefine origin for shift offset calculation
197  *
198  * Revision 1.11 1999/03/15 13:48:20 lasiuk
199  * xyFromRow is changed to take into account the inversion.
200  * The local coordinate system should be rechecked to make
201  * sure it is defined as the STAR Coordinate system!
202  *
203  * Revision 1.10 1999/03/02 17:52:10 lasiuk
204  * rotation for sectors>12
205  *
206  * Revision 1.9 1999/02/24 19:31:25 lasiuk
207  * allow for tZero offset
208  * positive pushes time bins into the chamber
209  *
210  * Revision 1.8 1999/02/18 21:17:27 lasiuk
211  * instantiate with electronics db
212  *
213  * Revision 1.7 1999/02/16 23:28:59 lasiuk
214  * matrix(3) is a data member to avoid constructor calls
215  * protection against pad<1
216  * const removed from several functions (because of matrix)
217  *
218  * Revision 1.6 1999/02/16 18:15:41 fisyak
219  * Check in the latest updates to fix them
220  *
221  * Revision 1.5 1999/02/12 01:26:36 lasiuk
222  * Limit debug output
223  *
224  * Revision 1.4 1999/02/10 04:23:24 lasiuk
225  * HP namespace
226 
227  *
228  * Revision 1.3 1999/01/28 02:51:27 lasiuk
229  * add ()localSector --> Raw
230  * add ()localSector --> Local
231  *
232  * Revision 1.2 1999/01/15 11:03:59 lasiuk
233  * sector 12/24 compatibility
234  *
235  * Revision 1.1 1998/11/10 17:12:20 fisyak
236  * Put Brian trs versin into StRoot
237  *
238  * Revision 1.5 1998/11/01 16:20:36 lasiuk
239  * remove 'St' from variable declarations
240  *
241  * Revision 1.4 1998/10/22 00:24:19 lasiuk
242  * Oct 22
243  *
244  * Revision 1.3 1998/06/04 23:24:09 lasiuk
245  * add sector12 coordinate transform as a public member
246  *
247  * Revision 1.2 1998/05/25 17:05:25 lasiuk
248  * use databases instead of filenames
249  *
250  * Revision 1.1 1998/05/21 21:27:57 lasiuk
251  * Initial revision
252  *
253  *
254  ***********************************************************************/
255 #include "StTpcCoordinateTransform.hh"
256 #include "StMatrix.hh"
257 #include <unistd.h>
258 #include "StMessMgr.h"
259 #include "StDetectorDbMaker/St_tpcPadrowT0C.h"
260 #include "StDetectorDbMaker/St_tpcSectorT0offsetC.h"
261 #include "StDetectorDbMaker/St_tpcRDOT0offsetC.h"
262 #include "StDetectorDbMaker/St_tss_tssparC.h"
263 #include "StDetectorDbMaker/St_tpcPadGainT0BC.h"
264 #include "StDetectorDbMaker/St_tpcPadConfigC.h"
265 #include "StDetectorDbMaker/St_tpcPadPlanesC.h"
266 #include "StDetectorDbMaker/St_iTPCSurveyC.h"
267 #include "StDetectorDbMaker/St_starTriggerDelayC.h"
268 #include "TMath.h"
269 #include "StThreeVectorD.hh"
270 #if defined (__SUNPRO_CC) && __SUNPRO_CC >= 0x500
271 using namespace units;
272 #endif
273 static Int_t _debug = 0;
274 StTpcCoordinateTransform::StTpcCoordinateTransform(StTpcDb* /* globalDbPointer */)
275  {
276  if (St_tpcPadConfigC::instance()
277  && StTpcDb::instance()->Electronics()
278 #if 0
279  && StTpcDb::instance()->GlobalPosition()
280 #endif
281  ) {
282  mTimeBinWidth = 1./StTpcDb::instance()->Electronics()->samplingFrequency();
283  mInnerSectorzOffset = StTpcDb::instance()->Dimensions()->zInnerOffset();
284  mOuterSectorzOffset = StTpcDb::instance()->Dimensions()->zOuterOffset();
285 #if 0
286  mInnerSectorzOffset_West = StTpcDb::instance()->Dimensions()->zInnerOffset_West();
287  mOuterSectorzOffset_West = StTpcDb::instance()->Dimensions()->zOuterOffset_West();
288 #endif
289  }
290  else {
291  gMessMgr->Error() << "StTpcDb IS INCOMPLETE! Cannot contstruct Coordinate transformation." << endm;
292  assert(St_tpcPadConfigC::instance());
293  assert(StTpcDb::instance()->Electronics());
294 #if 0
295  assert(StTpcDb::instance()->GlobalPosition());
296 #endif
297  }
298 }
299 //________________________________________________________________________________
300 // Local Sector Coordnate <-> Tpc Raw Pad Coordinate
301 void StTpcCoordinateTransform::operator()(const StTpcLocalSectorCoordinate& a, StTpcPadCoordinate& b, Bool_t useT0, Bool_t useTau)
302 { // useT0 = kTRUE for pad and kFALSE for cluster, useTau = kTRUE for data cluster and = kFALSE for MC
303  Int_t sector = a.fromSector();
304  Int_t row = a.fromRow();
305  if (row < 1 || row > St_tpcPadConfigC::instance()->numberOfRows(sector)) row = rowFromLocal(a);
306 
307  Double_t probablePad = padFromLocal(a);
308 #if 0 /* Don't apply zOffSet for prompt hits */
309  Double_t zoffset = 0; // Don't apply zOffSet for prompt hits
310  if (a.position().z() < 3) zoffset = (row>St_tpcPadConfigC::instance()->innerPadRows(sector)) ? mOuterSectorzOffset :mInnerSectorzOffset;
311 #else
312  Double_t zoffset = (row>St_tpcPadConfigC::instance()->innerPadRows(sector)) ? mOuterSectorzOffset :mInnerSectorzOffset;
313 #endif /* Don't apply zOffSet for prompt hits */
314 #if 0
315  if (sector <= 12) zoffset+= (row>St_tpcPadConfigC::instance()->innerPadRows(sector)) ? mOuterSectorzOffset_West :mInnerSectorzOffset_West;
316 #endif
317  Double_t t0offset = (useT0 && sector>=1&&sector<=24) ? St_tpcPadGainT0BC::instance()->T0(sector,row,TMath::Nint (probablePad)) : 0;
318  t0offset *= mTimeBinWidth;
319  if (! useT0 && useTau) // for cluster
320  t0offset -= 3.0 * St_tss_tssparC::instance()->tau(); // correct for convolution lagtime
321  Double_t t0zoffset = t0offset*StTpcDb::instance()->DriftVelocity(sector,row)*1e-6;
322  Double_t tb = tBFromZ(a.position().z()+zoffset-t0zoffset,sector,row,probablePad);
323  b = StTpcPadCoordinate(sector, row, probablePad, tb);
324 }
325 //________________________________________________________________________________
326 void StTpcCoordinateTransform::operator()(const StTpcPadCoordinate& a, StTpcLocalSectorCoordinate& b, Bool_t useT0, Bool_t useTau)
327 { // useT0 = kTRUE for pad and kFALSE for cluster, useTau = kTRUE for data cluster and = kFALSE for MC
328  StThreeVector<double> tmp=xyFromRow(a);
329  Int_t sector = a.sector();
330 #if 0 /* Don't apply zOffSet for prompt hits */
331  Double_t zoffset= 0; // Don't apply zOffSet for prompt hits
332  if (a.timeBucket() > 6) zoffset = (a.row()>St_tpcPadConfigC::instance()->innerPadRows(sector)) ? mOuterSectorzOffset : mInnerSectorzOffset;
333 #else
334  Double_t zoffset = (a.row()>St_tpcPadConfigC::instance()->innerPadRows(sector)) ? mOuterSectorzOffset : mInnerSectorzOffset;
335 #endif /* Don't apply zOffSet for prompt hits */
336 #if 0
337  if (a.sector() <= 12) zoffset+= (a.row() > St_tpcPadConfigC::instance()->innerPadRows(sector)) ? mOuterSectorzOffset_West :mInnerSectorzOffset_West;
338 #endif
339  Double_t t0offset = useT0 ? St_tpcPadGainT0BC::instance()->T0(a.sector(),a.row(),TMath::Nint(a.pad())) : 0;
340  t0offset *= mTimeBinWidth;
341  if (! useT0 && useTau) // for cluster
342  t0offset -= 3.0 * St_tss_tssparC::instance()->tau(); // correct for convolution lagtime
343  Double_t t0zoffset = t0offset*StTpcDb::instance()->DriftVelocity(a.sector(),a.row())*1e-6;
344  //t0 offset -- DH 27-Mar-00
345  Double_t z = zFromTB(a.timeBucket(),a.sector(),a.row(),a.pad())-zoffset+t0zoffset;
346  tmp.setZ(z);
347  b = StTpcLocalSectorCoordinate(tmp,a.sector(),a.row());
348 }
349 //________________________________________________________________________________
350 Double_t StTpcCoordinateTransform::padFromX(Double_t x, Int_t sector, Int_t row) const {
351  if (row > St_tpcPadConfigC::instance()->numberOfRows(sector)) row = St_tpcPadConfigC::instance()->numberOfRows(sector);
352  Double_t pitch = (row <= St_tpcPadConfigC::instance()->innerPadRows(sector)) ?
353  St_tpcPadConfigC::instance()->innerSectorPadPitch(sector) :
354  St_tpcPadConfigC::instance()->outerSectorPadPitch(sector);
355  // x coordinate in sector 12
356  Int_t npads = St_tpcPadConfigC::instance()->numberOfPadsAtRow(sector,row);
357  Double_t xL = x;
358  Int_t NiRows = St_tpcPadConfigC::instance()->numberOfInnerRows(sector);
359  if (NiRows != 13 && row <= NiRows) {
360  // iTPC Survey, see Jim Thomas comments in StTpcCoordinateTransform::xFromPad
361  Double_t yRef = St_tpcPadConfigC::instance()->radialDistanceAtRow(sector,NiRows) + 0.565;
362  Double_t xHit = xL;
363  Double_t yHit = St_tpcPadConfigC::instance()->radialDistanceAtRow(sector,row) - yRef;
364  St_iTPCSurveyC *sur = St_iTPCSurveyC::instance();
365  Double_t dx = sur->dx(sector-1);
366 // Double_t dy = sur->dy(sector-1);
367  Double_t Xscale = sur->ScaleX(sector-1);
368 // Double_t Yscale = sur->ScaleY(sector-1);
369  Double_t theta = sur->Angle(sector-1);
370  xL = xHit*(1. - Xscale) - dx + theta*yHit;
371 // Double_t yL = yHit*(1. - Yscale) - dy - theta*xHit + yRef;
372  }
373  Double_t probablePad = (npads+1.)/2. - xL/pitch;
374  // CAUTION: pad cannot be <1
375  if(probablePad<0.500001) {
376  probablePad=0.500001;
377  }
378  if (_debug) {
379  cout << "StTpcCoordinateTransform::padFromX(" << x << "," << sector << "," << row << "); npads = " << npads << ", pitch = " << pitch
380  << "\tprobablePad " << probablePad << endl;
381  }
382  return (probablePad);
383 }
384 //________________________________________________________________________________
385 Double_t StTpcCoordinateTransform::xFromPad(Int_t sector, Int_t row, Double_t pad) const { // x coordinate in sector 12
386  if (row > St_tpcPadConfigC::instance()->numberOfRows(sector)) row = St_tpcPadConfigC::instance()->numberOfRows(sector);
387  Double_t pitch = (row <= St_tpcPadConfigC::instance()->innerPadRows(sector)) ?
388  St_tpcPadConfigC::instance()->innerSectorPadPitch(sector) :
389  St_tpcPadConfigC::instance()->outerSectorPadPitch(sector);
390  Int_t npads = St_tpcPadConfigC::instance()->numberOfPadsAtRow(sector,row);
391  Double_t xPad = -pitch*(pad - (npads+1.)/2.);
392  if (_debug) {
393  cout << "StTpcCoordinateTransform::xFromPad(" << sector << "," << row << "," << pad << "); npads = " << npads << ", pitch = " << pitch
394  << "\txPad = " << xPad << endl;
395  }
396  Int_t NiRows = St_tpcPadConfigC::instance()->numberOfInnerRows(sector);
397  if (NiRows == 13 || row > NiRows) {
398  return xPad;
399  }
400  // iTPC Survey, Jim Thomas correction 08/21/18
401  // The change in the yRef comes about because the origin of the coordinate system is 0.565 mm above the center of PadRow 40.
402  // The changes for the X coordinates come about because of the reversal of pad counting by the DAQ guys … as you know.
403  Double_t yRef = St_tpcPadConfigC::instance()->radialDistanceAtRow(sector,NiRows) + 0.565; // Change sign in front of 0.565
404  Double_t xL = xPad; // Eliminate -1 in front of xPad
405  Double_t yL = St_tpcPadConfigC::instance()->radialDistanceAtRow(sector,row) - yRef;
406  St_iTPCSurveyC *sur = St_iTPCSurveyC::instance();
407  Double_t dx = sur->dx(sector-1);
408 //Double_t dy = sur->dy(sector-1);
409  Double_t Xscale = sur->ScaleX(sector-1);
410 //Double_t Yscale = sur->ScaleY(sector-1);
411  Double_t theta = sur->Angle(sector-1);
412  Double_t xHit = xL*(1. + Xscale) + dx - theta*yL; // Eliminate -1 in front of whole expression and delete ( )
413 //Double_t yHit = yL*(1. + Yscale) + dy + theta*xL + yRef;
414  return xHit;
415 }
416 // Coordinate from Row
417 //
418 //Local Transformation...
419 //________________________________________________________________________________
420 Double_t StTpcCoordinateTransform::zFromTB(Double_t tb, Int_t sector, Int_t row, Int_t pad) const {
421  if (row > St_tpcPadConfigC::instance()->numberOfRows(sector)) row = St_tpcPadConfigC::instance()->numberOfRows(sector);
422  Double_t trigT0 = 0;
423  Double_t elecT0 = 0;
424  if (! St_starTriggerDelayC::instance()->Table()->IsMarked()) {// new scheme: offset = clocks*timebin + t0
425  trigT0 = St_starTriggerDelayC::instance()->clocks()*mTimeBinWidth;
426  elecT0 = St_starTriggerDelayC::instance()->tZero();
427  } else { // old scheme
428  trigT0 = StTpcDb::instance()->triggerTimeOffset()*1e6; // units are s
429 #if 0
430  if ((sector <= 12 && tb <= 350) || // extra West laser off set, membrane cluster with time bucket > 350
431  (sector > 12 && tb > 350)) {trigT0 += StTpcDb::instance()->triggerTimeOffsetWest()*1e6;}
432 #endif
433  elecT0 = StTpcDb::instance()->Electronics()->tZero(); // units are us
434  }
435  Double_t sectT0 = St_tpcPadrowT0C::instance()->T0(sector,row);// units are us
436  Double_t t0 = trigT0 + elecT0 + sectT0;
437  Int_t l = sector;
438  if ( St_tpcPadConfigC::instance()->IsRowInner(sector,row)) l += 24;
439  Double_t tbx = tb + St_tpcSectorT0offsetC::instance()->t0offset(l);
440  if (St_tpcRDOT0offsetC::instance()->IsShfited(sector)) {
441  tbx += St_tpcRDOT0offsetC::instance()->T0(sector,row,pad);
442  }
443  Double_t time = t0 + tbx*mTimeBinWidth;
444  Double_t z = StTpcDb::instance()->DriftVelocity(sector,row)*1e-6*time;
445  return z;
446 }
447 //________________________________________________________________________________
448 Double_t StTpcCoordinateTransform::tBFromZ(Double_t z, Int_t sector, Int_t row, Int_t pad) const {
449  if (row > St_tpcPadConfigC::instance()->numberOfRows(sector)) row = St_tpcPadConfigC::instance()->numberOfRows(sector);
450  Double_t trigT0 = 0;
451  Double_t elecT0 = 0;
452  if (! St_starTriggerDelayC::instance()->Table()->IsMarked()) {// new scheme: offset = clocks*timebin + t0
453  trigT0 = St_starTriggerDelayC::instance()->clocks()*mTimeBinWidth;
454  elecT0 = St_starTriggerDelayC::instance()->tZero();
455  } else { // old scheme
456  trigT0 = StTpcDb::instance()->triggerTimeOffset()*1e6; // units are s
457 #if 0
458  if ((sector <= 12 && z < 195) || // extra West laser off set, membrane cluster with time z < 195
459  (sector > 12 && z > 195)) {trigT0 += StTpcDb::instance()->triggerTimeOffsetWest()*1e6;}
460 #endif
461  elecT0 = StTpcDb::instance()->Electronics()->tZero(); // units are us
462  }
463  Double_t sectT0 = St_tpcPadrowT0C::instance()->T0(sector,row);// units are us
464  Double_t t0 = trigT0 + elecT0 + sectT0;
465  Double_t time = z / (StTpcDb::instance()->DriftVelocity(sector,row)*1e-6);
466  Int_t l = sector;
467  if ( St_tpcPadConfigC::instance()->IsRowInner(sector,row)) l += 24;
468  Double_t tb = (time - t0)/mTimeBinWidth - St_tpcSectorT0offsetC::instance()->t0offset(l);
469  if (St_tpcRDOT0offsetC::instance()->IsShfited(sector)) tb -= St_tpcRDOT0offsetC::instance()->T0(sector,row,pad);
470  return tb;
471 }
472 //________________________________________________________________________________
473 // FOR SECTOR 12 ONLY!!!! (Local coordinate);
474 Int_t StTpcCoordinateTransform::rowFromLocalY(Double_t y, Int_t sector) {
475  static Int_t Nrows = 0;
476  static Double_t *Radii = 0;
477 #ifndef __OLD__
478  if (Nrows != St_tpcPadConfigC::instance()->padRows(sector)) {
479  Nrows = St_tpcPadConfigC::instance()->padRows(sector);
480  if (Radii) delete [] Radii;
481  Radii = new Double_t[Nrows+1];
482  for (Int_t i = 1; i <= Nrows+1; i++) {
483  if (i == 1) {
484  Radii[i-1] = (3*St_tpcPadConfigC::instance()->radialDistanceAtRow(sector,i)
485  - St_tpcPadConfigC::instance()->radialDistanceAtRow(sector,i+1))/2;
486  } else if (i == Nrows + 1) {
487  Radii[i-1] = (3*St_tpcPadConfigC::instance()->radialDistanceAtRow(sector,i-1)
488  - St_tpcPadConfigC::instance()->radialDistanceAtRow(sector,i-2))/2;
489  } else {
490  Radii[i-1] = (St_tpcPadConfigC::instance()->radialDistanceAtRow(sector,i-1) +
491  St_tpcPadConfigC::instance()->radialDistanceAtRow(sector,i))/2;
492  }
493  }
494  }
495  Long64_t row = TMath::BinarySearch(Nrows+1, Radii, y) + 1;
496  if (row <= 0) row = 1;
497  if (row > Nrows) row = Nrows;
498  return row;
499 #else
500  if (! Nrows) {
501  Nrows = St_tpcPadPlanesC::instance()->padRows();
502  Radii = new Double_t[Nrows];
503  for (Int_t i = 1; i <= Nrows; i++) {
504  Radii[i-1] = St_tpcPadPlanesC::instance()->radialDistanceAtRow(i);
505  }
506  }
507  if (y < Radii[0]) return 1;
508  if (y > Radii[Nrows-1]) return Nrows;
509  Long64_t row = TMath::BinarySearch(Nrows, Radii, y);
510  if (row < Nrows - 1) {
511  if (TMath::Abs(Radii[row]-y) > TMath::Abs(Radii[row+1]-y)) row++;
512  }
513  row++;
514  return row;
515 #endif
516 }
517 //________________________________________________________________________________
518 void StTpcCoordinateTransform::operator()(const StTpcLocalSectorCoordinate& a, StTpcLocalCoordinate& b )
519 {
520  StThreeVectorD xGG;
521  Int_t row = a.fromRow();
522  Int_t sector = a.fromSector();
523  if (row < 1 || row > St_tpcPadConfigC::instance()->numberOfRows(sector)) row = rowFromLocal(a);
524  StTpcDb::instance()->Pad2Tpc(a.sector(),row).LocalToMasterVect(a.position().xyz(),xGG.xyz());
525  const Double_t *trans = StTpcDb::instance()->Pad2Tpc(sector,row).GetTranslation(); // 4
526  TGeoTranslation GG2TPC(trans[0],trans[1],trans[2]);
527  GG2TPC.LocalToMaster(xGG.xyz(), b.position().xyz());
528  b.setSector(a.sector()); b.setRow(row);
529 }
530 //________________________________________________________________________________
531 void StTpcCoordinateTransform::operator()(const StTpcLocalCoordinate& a, StTpcLocalSectorCoordinate& b )
532 {
533  Int_t row = a.fromRow();
534  Int_t sector = a.fromSector();
535  if ( ! (row >= 1 && row <= St_tpcPadConfigC::instance()->numberOfRows(sector))) {
536  StThreeVectorD xyzS;
537  StTpcDb::instance()->SupS2Tpc(sector).MasterToLocalVect(a.position().xyz(),xyzS.xyz());
538  row = rowFromLocalY(xyzS[0], sector);
539  }
540  const Double_t *trans = StTpcDb::instance()->Pad2Tpc(a.sector(),row).GetTranslation(); // 4
541  TGeoTranslation GG2TPC(trans[0],trans[1],trans[2]);
542  StThreeVectorD xGG;
543  GG2TPC.MasterToLocal(a.position().xyz(), xGG.xyz());
544  StTpcDb::instance()->Pad2Tpc(a.sector(),row).MasterToLocalVect(xGG.xyz(),b.position().xyz()); b.setSector(a.sector()); b.setRow(row);
545 }