EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TrKalmanNodeLocation.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file TrKalmanNodeLocation.cxx
1 //
2 // AYK (ayk@bnl.gov)
3 //
4 // Extracted from KalmanNode in Oct'2015;
5 //
6 
7 #include <assert.h>
8 
9 #include <htclib.h>
10 
11 #include <MediaBank.h>
12 #include <TrKalmanNode.h>
13 #include <TrKalmanNodeLocation.h>
14 
15 // =======================================================================================
16 
17 static void fill_lower_triangle(double **mtx, int dim)
18 {
19  int ip, iq;
20 
21  for(ip=1; ip<dim; ip++)
22  for(iq=0; iq<ip; iq++)
23  mtx[ip][iq] = mtx[iq][ip];
24 } /* fill_lower_triangle */
25 
26 //
27 // -> move this stuff to some common place later!;
28 //
29 
30 // ---------------------------------------------------------------------------------------
31 
32 // FIXME: this crap should go at some point;
33 
34 static void *allocate_2dim_array(int dim1, int dim2, int element_size)
35 {
36  int ip;
37  void **arr = (void**)malloc(dim1*sizeof(void*));
38 
39  if (!arr) return NULL;
40 
41  for(ip=0; ip<dim1; ip++)
42  {
43  arr[ip] = (void*)calloc(dim2, element_size);
44  if (!arr[ip]) return NULL;
45  } /*for*/
46 
47  return arr;
48 } /* allocate_2dim_array */
49 
50 // ---------------------------------------------------------------------------------------
51 
52 static void *allocate_2dim_double_array(int dim1, int dim2)
53 {
54  return allocate_2dim_array(dim1, dim2, sizeof(double));
55 } /* allocate_2dim_double_array */
56 
57 // =======================================================================================
58 
60 {
61  MediaSliceArray *array;
62  double F[4][4], Cms, D;
63  ProcessNoise *noise = new ProcessNoise();
64  //if (!noise) return NULL;
65 
66  // FIXME: should go to the ProcessNoise constructor at some point;
67  noise->mCxx = (double**)allocate_2dim_double_array(4, 4);
68  noise->mCyy = (double**)allocate_2dim_double_array(4, 4);
69  noise->mCxy = (double**)allocate_2dim_double_array(4, 4);
70  if (!noise->mCxx || !noise->mCyy || !noise->mCxy) return NULL;
71 
72  // Initialize field-free transport matrix to unity;
73  memset(F, 0x00, sizeof(F));
74  for(int iq=0; iq<4; iq++)
75  F[iq][iq] = 1.0;
76 
77  if (fb == KalmanFilter::Forward) {
78  array = mMediaSliceArray;
79  D = 1.;
80  }
81  else {
83  D = -1.;
84  } //if
85 
86  // I know that it is in general a bad idea to handle layers
87  // separately (one should in principle calculate total rad.length
88  // first); but for thick layers it is otherwise hard to take [x,sx]
89  // correlations into account; anyway, later may try to do it better;
90  for(int ik=0; ik<array->GetMediaSliceCount(); ik++) {
91  MediaSlice *mslice = array->GetMediaSlice(ik);
92 
93  // Material properties unknown --> skip;
94  assert(mslice->GetMediaLayer()->GetMaterial());
95 
96  // Calculate transport matrix for this slice to reach array back
97  // or front end; apparently this is strictly valid for the field-free case only;
98  if (fb == KalmanFilter::Forward)
99  F[0][2] = F[1][3] = array->GetThickness() - (mslice->GetZ0() - array->GetZ0()) - mslice->GetThickness();
100  else
101  F[0][2] = F[1][3] = - (mslice->GetZ0() - array->GetZ0());
102 
103  // Calculate process noise covariance matrix contributions;
104  // NB: memset() resetted all other fields to '0' already;
105  mslice->_RCxx[fb][0][0] = SQR(mslice->GetThickness())/3.;
106  mslice->_RCxx[fb][0][2] = mslice->_RCxx[fb][2][0] = D*mslice->GetThickness() /2.;
107  mslice->_RCxx[fb][2][2] = 1.;
108 
109  mslice->_RCyy[fb][1][1] = SQR(mslice->GetThickness())/3.;
110  mslice->_RCyy[fb][1][3] = mslice->_RCyy[fb][3][1] = D*mslice->GetThickness() /2.;
111  mslice->_RCyy[fb][3][3] = 1.;
112 
113  mslice->_RCxy[fb][0][1] = mslice->_RCxy[fb][1][0] = SQR(mslice->GetThickness())/3.;
114  mslice->_RCxy[fb][0][3] = mslice->_RCxy[fb][3][0] = D*mslice->GetThickness() /2.;
115  mslice->_RCxy[fb][1][2] = mslice->_RCxy[fb][2][1] = D*mslice->GetThickness() /2.;
116  mslice->_RCxy[fb][2][3] = mslice->_RCxy[fb][3][2] = 1.;
117 
118  // Well, keep both options in the source code; Moliere theory is not
119  // available in GEANT4;
120 #ifdef _USE_GEANT3_MOLIERE_CHC_
121  // This is according to the gaussian model and should perfectly reproduce
122  // MULS=3 multiple scattering model in GEANT; 1./(E*beta**2) will be
123  // added in initialize_process_noise();
124  Cms = SQR(2.557*mslice->GetMediaLayer()->GetMoliereChc())*mslice->GetThickness();
125 #else
126  // This approach indeed ignores slope coefficient under log() term;
127  Cms = SQR(13.6E-3)*(mslice->GetReducedRadiationLength())*
128  SQR(1. + 0.038*log(mslice->GetReducedRadiationLength()));
129 #endif
130 
131  for(int ip=0; ip<4; ip++)
132  for(int iq=0; iq<4; iq++)
133  for(int ir=0; ir<4; ir++)
134  for(int is=ip; is<4; is++)
135  {
136  noise->mCxx[ip][is] += Cms*F[ip][iq]*mslice->_RCxx[fb][iq][ir]*F[is][ir];
137  noise->mCyy[ip][is] += Cms*F[ip][iq]*mslice->_RCyy[fb][iq][ir]*F[is][ir];
138  noise->mCxy[ip][is] += Cms*F[ip][iq]*mslice->_RCxy[fb][iq][ir]*F[is][ir];
139  } /*for..for*/
140  } /*for*/
141  fill_lower_triangle(noise->mCxx, 4);
142  fill_lower_triangle(noise->mCyy, 4);
143  fill_lower_triangle(noise->mCxy, 4);
144 
145  return noise;
146 } // TrKalmanNodeLocation::InitializeProcessNoiseMatrices()
147 
148 // ---------------------------------------------------------------------------------------
149 
151 {
152  unsigned counter = 0;
153 
154  for(unsigned nd=0; nd<mNodes.size(); nd++) {
155  TrKalmanNode *node = mNodes[nd];
156 
157  if (node->IsActive() && node->IsFired()) counter++;
158  } //for nd
159 
160  return counter;
161 } // TrKalmanNodeLocation::GetFiredNodeCount()
162 
163 // ---------------------------------------------------------------------------------------
164 #if 0
166 {
167  for(unsigned nd=0; nd<mNodes.size(); nd++) {
168  TrKalmanNode *node = mNodes[nd];
169 
170  if (node->GetSensitiveVolume()) return true;
171  } //for nd
172 
173  return false;
174 } // TrKalmanNodeLocation::HasSensitiveVolumes()
175 #endif
176 // ---------------------------------------------------------------------------------------