Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DFDCPseudo.h
Go to the documentation of this file.
1 //***********************************************************************
2 // DFDCPseudo.h : definition for a set of FDCHits that have gone
3 // through first-order reconstruction.
4 // Author: Craig Bookwalter (craigb at jlab.org)
5 // Date: March 2006
6 //***********************************************************************
7 
8 #ifndef DFDCPSEUDO_H
9 #define DFDCPSEUDO_H
10 
11 #include <JANA/JObject.h>
12 using namespace jana;
13 
14 #include "DFDCWire.h"
15 #include "DFDCCathodeCluster.h"
16 #include <sstream>
17 #include <vector>
18 #include <DVector2.h>
19 #include <DMatrix.h>
20 #include <DMatrixSIMD.h>
21 
22 typedef struct {
23  double pos;
24  double q;
26  int numstrips;
27  double t; // mean time of strips in peak
28  double t_rms; // rms of strips in peak
29  unsigned int cluster; // index for cluster from which this centroid was generated
30  DMatrix3x1 X,N,NRaw,index;
31 }centroid_t;
32 
33 enum FDCTrackD {
54 };
55 
56 enum FDCPseudoD {
69 };
70 
71 ///
72 /// class DFDCPseudo: definition for a reconstructed point in the FDC
73 ///
74 class DFDCPseudo : public JObject {
75  public :
76  JOBJECT_PUBLIC(DFDCPseudo); /// DANA identifier
77 
78  ///
79  /// DFDCPseudo::DFDCPseudo():
80  /// Default constructor-- provide the X, Y, global layer #, and resolution
81  ///
83 
84 
85  double u,v; ///< centroid positions in the two cathode views
86  double t_u,t_v; ///< time of the two cathode clusters
87  double phi_u,phi_v; ///< rotation angles for cathode planes
88  centroid_t cluster_u, cluster_v; ///< Cathode cluster centroids, Useful for gain/strip pitch calibration.
89  double w,dw; ///< local coordinate of pseudopoint in the direction perpendicular to the wires and its uncertainty
90  double w_c; /// < wire position computed from cathode data, assuming the avalanche occurs at the wire
91  double s,ds; ///< local coordinate of pseudopoint in the direction along the wire and its uncertainty
92  const DFDCWire* wire; ///< DFDCWire for this wire
93  double time; ///< time corresponding to this pseudopoint.
94  int status; ///< status word for pseudopoint
95  double covxx,covxy,covyy; ///< Covariance terms for (x,y)
96  double dE; ///< energy deposition, from integral
97  double dE_amp; /// < energy deposition, from pulse height
98  double q; ///< anode charge deduced from cathode strips
99  int itrack;
100  DVector2 xy; ///< rough x,y coordinates in lab coordinate system
101 
102  void toStrings(vector<pair<string,string> > &items)const{
103  AddString(items,"u","%3.2f",u);
104  AddString(items,"v","%3.2f",v);
105  AddString(items,"t_u","%3.2f",t_u);
106  AddString(items,"t_v","%3.2f",t_v);
107  AddString(items,"phi_u","%3.2f",phi_u);
108  AddString(items,"phi_v","%3.2f",phi_v);
109  AddString(items, "w", "%3.4f", w);
110  AddString(items, "w_c", "%3.4f", w_c);
111  AddString(items, "s", "%3.4f", s);
112  AddString(items, "layer", "%d", wire->layer);
113  AddString(items, "wire", "%d", wire->wire);
114  AddString(items, "time", "%3.1f", time);
115  AddString(items, "status", "%d", status);
116  AddString(items, "x", "%.4f", xy.X());
117  AddString(items, "y", "%.4f", xy.Y());
118  AddString(items, "dE", "%3.1f", dE);
119  }
120 
121  // For alignment purposes the residuals wrt the alignment parameters are needed.
122  // These routines calculate the derivatives of the "s" and "w" variables wrt the alignment parameters
123  // Currently implemented alignment parameters are dU, dV, dPhiU, dPhiV, dX (Acts in direction w), dY (acts in direction s)
124 
126  // Create the storage vector for each of the derivatives
127  size_t nDerivatives = 12;
128  vector<double> derivatives(nDerivatives);
129 
130  // Useful numbers...
131  double sinPhiU = sin(phi_u);
132  double cosPhiU = cos(phi_u);
133  double sinPhiV = sin(phi_v);
134  double cosPhiV = cos(phi_v);
135  double sinPhiUmPhiV = sin(phi_u-phi_v);
136  double sinPhiUmPhiV2 = sinPhiUmPhiV*sinPhiUmPhiV;
137  double cosPhiUmPhiV = cos(phi_u-phi_v);
138 
139  // Calculate the derivatives
140  derivatives[dWcddeltaU] = sinPhiV/sinPhiUmPhiV;
141  derivatives[dWcddeltaV] = -sinPhiU/sinPhiUmPhiV;
142  derivatives[dWcddeltaPhiU] = (v-u*cosPhiUmPhiV)*sinPhiV/sinPhiUmPhiV2;
143  derivatives[dWcddeltaPhiV] = (u-v*cosPhiUmPhiV)*sinPhiU/sinPhiUmPhiV2;
144 
145  derivatives[dSddeltaU] = -cosPhiV/sinPhiUmPhiV;
146  derivatives[dSddeltaV] = cosPhiU/sinPhiUmPhiV;
147  derivatives[dSddeltaPhiU] = -(v-u*cosPhiUmPhiV)*cosPhiV/sinPhiUmPhiV2;
148  derivatives[dSddeltaPhiV] = -(u-v*cosPhiUmPhiV)*cosPhiU/sinPhiUmPhiV2;
149 
150  derivatives[dWdX]=1.0;
151  derivatives[dSdX]=1.0;
152 
153  derivatives[dWddeltaPhiWz]=-s; // For small angles. Rotations of the wire plane about the z axis
154  derivatives[dWddeltaPhiWy]=-w; // Rotations about the wire axis
155 
156  return derivatives;
157 
158  }
159 
160  vector<double> GetFDCStripGainDerivatives() {
161  // Numerically calculate the derivatives of the cathode position wrt the strip gains
162  // Numerical calculation necessary since it comes from the solution of a nonlinear set of equations
163  vector<double> derivatives; // u and v
164 
165  // Loop over the cluster and find the three hit section used
166  double positionNominal, positionShifted;
167  FindCentroid(cluster_u.N, cluster_u.X, positionNominal);
168 
169  double delta = 0.05;
170 
171  DMatrix3x1 deltaVectU0(delta*cluster_u.NRaw(0), 0.0, 0.0);
172  DMatrix3x1 deltaVectU1(0.0,delta*cluster_u.NRaw(1), 0.0);
173  DMatrix3x1 deltaVectU2(0.0,0.0,delta*cluster_u.NRaw(2));
174 
175  DMatrix3x1 deltaVectV0(delta*cluster_v.NRaw(0), 0.0, 0.0);
176  DMatrix3x1 deltaVectV1(0.0,delta*cluster_v.NRaw(1), 0.0);
177  DMatrix3x1 deltaVectV2(0.0,0.0,delta*cluster_v.NRaw(2));
178 
179  FindCentroid(cluster_u.N+deltaVectU0, cluster_u.X, positionShifted);
180  derivatives.push_back((positionShifted-positionNominal)/delta);
181 
182  FindCentroid(cluster_u.N+deltaVectU1, cluster_u.X, positionShifted);
183  derivatives.push_back((positionShifted-positionNominal)/delta);
184 
185  FindCentroid(cluster_u.N+deltaVectU2, cluster_u.X, positionShifted);
186  derivatives.push_back((positionShifted-positionNominal)/delta);
187 
188  FindCentroid(cluster_v.N, cluster_v.X, positionNominal);
189 
190  FindCentroid(cluster_v.N+deltaVectV0, cluster_v.X, positionShifted);
191  derivatives.push_back((positionShifted-positionNominal)/delta);
192 
193  FindCentroid(cluster_v.N+deltaVectV1, cluster_v.X, positionShifted);
194  derivatives.push_back((positionShifted-positionNominal)/delta);
195 
196  FindCentroid(cluster_v.N+deltaVectV2, cluster_v.X, positionShifted);
197  derivatives.push_back((positionShifted-positionNominal)/delta);
198 
199  //jout << " New Hit" << endl;
200  //for (size_t i=0 ; i < derivatives.size(); i++){
201  // jout << "i " << i << " der " << derivatives[i] << endl;
202  //}
203 
204  return derivatives;
205  }
206 
207  const vector<double> GetFDCStripPitchDerivatives(){
208  // Numerically calculate the derivatives of the cathode position wrt the strip gains
209  // Numerical calculation necessary since it comes from the solution of a nonlinear set of equations
210  vector<double> derivatives; // u and v
211 
212  double positionNominal, positionShifted;
213  FindCentroid(cluster_u.N, cluster_u.X, positionNominal);
214 
215  double delta = 0.005;
216  DMatrix3x1 deltaVect(0.0, 0.0, 0.0);
217  // delta_U_SP_1
218  for (int i=0 ; i < 3; i++){
219  if(cluster_u.index(i) < 48) deltaVect(i) = (cluster_u.index(i)-47.)*delta;
220  else deltaVect(i) = 0.0;
221  }
222 
223  FindCentroid(cluster_u.N, cluster_u.X + deltaVect, positionShifted);
224  derivatives.push_back((positionShifted-positionNominal)/delta);
225 
226  // delta_U_G_1
227  for (int i=0 ; i < 3; i++){
228  if(cluster_u.index(i) < 48) deltaVect(i) = -delta;
229  else deltaVect(i) = 0.0;
230  }
231 
232  FindCentroid(cluster_u.N, cluster_u.X + deltaVect, positionShifted);
233  derivatives.push_back((positionShifted-positionNominal)/delta);
234 
235  // delta_U_SP_2
236  for (int i=0 ; i < 3; i++){
237  if(cluster_u.index(i) < 48) deltaVect(i) = -47.5*delta;
238  else if (cluster_u.index(i) < 144) deltaVect(i) = (cluster_u.index(i)-95.5)*delta;
239  else deltaVect(i) = 47.5*delta;
240  }
241 
242  FindCentroid(cluster_u.N, cluster_u.X + deltaVect, positionShifted);
243  derivatives.push_back((positionShifted-positionNominal)/delta);
244 
245  // delta_U_G_2
246  for (int i=0 ; i < 3; i++){
247  if(cluster_u.index(i) >= 144) deltaVect(i) = delta;
248  else deltaVect(i) = 0.0;
249  }
250 
251  FindCentroid(cluster_u.N, cluster_u.X + deltaVect, positionShifted);
252  derivatives.push_back((positionShifted-positionNominal)/delta);
253 
254  // delta_U_SP_3
255  for (int i=0 ; i < 3; i++){
256  if(cluster_u.index(i) >= 144) deltaVect(i) = (cluster_u.index(i)-144.)*delta;
257  else deltaVect(i) = 0.0;
258  }
259 
260  FindCentroid(cluster_u.N, cluster_u.X + deltaVect, positionShifted);
261  derivatives.push_back((positionShifted-positionNominal)/delta);
262 
263  //==========
264  // Get the nominal V shift
265  FindCentroid(cluster_v.N, cluster_v.X, positionNominal);
266 
267  // delta_V_SP_1
268  for (int i=0 ; i < 3; i++){
269  if(cluster_v.index(i) < 48) deltaVect(i) = (cluster_v.index(i)-47.)*delta;
270  else deltaVect(i) = 0.0;
271  }
272 
273  FindCentroid(cluster_v.N, cluster_v.X + deltaVect, positionShifted);
274  derivatives.push_back((positionShifted-positionNominal)/delta);
275 
276  // delta_V_G_1
277  for (int i=0 ; i < 3; i++){
278  if(cluster_v.index(i) < 48) deltaVect(i) = -delta;
279  else deltaVect(i) = 0.0;
280  }
281 
282  FindCentroid(cluster_v.N, cluster_v.X + deltaVect, positionShifted);
283  derivatives.push_back((positionShifted-positionNominal)/delta);
284 
285  // delta_V_SP_2
286  for (int i=0 ; i < 3; i++){
287  if(cluster_v.index(i) < 48) deltaVect(i) = -47.5*delta;
288  else if (cluster_v.index(i) < 144) deltaVect(i) = (cluster_v.index(i)-95.5)*delta;
289  else deltaVect(i) = 47.5*delta;
290  }
291 
292  FindCentroid(cluster_v.N, cluster_v.X + deltaVect, positionShifted);
293  derivatives.push_back((positionShifted-positionNominal)/delta);
294 
295  // delta_V_G_2
296  for (int i=0 ; i < 3; i++){
297  if(cluster_v.index(i) >= 144) deltaVect(i) = delta;
298  else deltaVect(i) = 0.0;
299  }
300 
301  FindCentroid(cluster_v.N, cluster_v.X + deltaVect, positionShifted);
302  derivatives.push_back((positionShifted-positionNominal)/delta);
303 
304  // delta_V_SP_3
305  for (int i=0 ; i < 3; i++){
306  if(cluster_v.index(i) >= 144) deltaVect(i) = (cluster_v.index(i)-144.)*delta;
307  else deltaVect(i) = 0.0;
308  }
309 
310  FindCentroid(cluster_v.N, cluster_v.X + deltaVect, positionShifted);
311  derivatives.push_back((positionShifted-positionNominal)/delta);
312 
313  return derivatives;
314 
315  }
316 
317  jerror_t FindCentroid(DMatrix3x1 N, DMatrix3x1 X, double &pos){
318 
319  unsigned int X0=0;
320  unsigned int QA=1;
321  unsigned int K2=2;
322  int ITER_MAX=100;
323  float TOLX=1e-4;
324  float TOLF=1e-4;
325  float A_OVER_H=0.4;
326  float ONE_OVER_H=2.0;
327 
328  // Define some matrices for use in the Newton-Raphson iteration
329  DMatrix3x3 J; //Jacobean matrix
330  DMatrix3x1 F,par,newpar,f;
331 
332  double sum=0.;
333 
334  for (int j=0; j<3; j++){
335  sum+=N(j);
336  }
337 
338  // Starting values for the minimization
339  par(X0)=X(1); // X0
340  par(QA)=2.*sum; // QA
341  par(K2)=1.; // K2
342  newpar=par;
343 
344  // Newton-Raphson procedure
345  double errf=0.,errx=0;
346  for (int iter=1;iter<=ITER_MAX;iter++){
347  errf=0.;
348  errx=0.;
349 
350  // Compute Jacobian matrix: J_ij = dF_i/dx_j.
351  for (int i=0;i<3;i++){
352  double dx=(par(X0)-X(i))*ONE_OVER_H;
353  double argp=par(K2)*(dx+A_OVER_H);
354  double argm=par(K2)*(dx-A_OVER_H);
355  double tanh_p=tanh(argp);
356  double tanh_m=tanh(argm);
357  double tanh2_p=tanh_p*tanh_p;
358  double tanh2_m=tanh_m*tanh_m;
359  double q_over_4=0.25*par(QA);
360 
361  f(i)=tanh_p-tanh_m;
362  J(i,QA)=-0.25*f(i);
363  J(i,K2)=-q_over_4*(argp/par(K2)*(1.-tanh2_p)
364  -argm/par(K2)*(1.-tanh2_m));
365  J(i,X0)=-q_over_4*par(K2)*(tanh2_m-tanh2_p);
366  F(i)=N(i)-q_over_4*f(i);
367  double new_errf=fabs(F(i));
368  if (new_errf>errf) errf=new_errf;
369  }
370  // Check for convergence
371  if (errf<TOLF){
372  pos = par(X0);
373  return NOERROR;
374  }
375 
376  // Find the new set of parameters
377  FindNewParmVec(N,X,F,J,par,newpar);
378 
379  //Check for convergence
380  for (int i=0;i<3;i++){
381  double new_err=fabs(par(i)-newpar(i));
382  if (new_err>errx) errx=new_err;
383  }
384  if (errx<TOLX){
385  pos = par(X0);
386  return NOERROR;
387  }
388  par=newpar;
389  } // iterations
390 
391  return INFINITE_RECURSION; // error placeholder
392  }
393 
394  jerror_t FindNewParmVec(const DMatrix3x1 &N,
395  const DMatrix3x1 &X,
396  const DMatrix3x1 &F,
397  const DMatrix3x3 &J,
398  const DMatrix3x1 &par,
399  DMatrix3x1 &newpar){
400 
401  unsigned int X0=0;
402  unsigned int QA=1;
403  unsigned int K2=2;
404  float A_OVER_H=0.4;
405  float ONE_OVER_H=2.0;
406  float ALPHA=1e-4; // rate parameter for Newton step backtracking algorithm
407 
408  // Invert the J matrix
409  DMatrix3x3 InvJ=J.Invert();
410 
411  // Find the full Newton step
412  DMatrix3x1 fullstep=(-1.)*(InvJ*F);
413 
414  // find the rate of decrease for the Newton-Raphson step
415  double slope=(-1.0)*F.Mag2(); //dot product
416 
417  // This should be a negative number...
418  if (slope>=0){
419  return VALUE_OUT_OF_RANGE;
420  }
421 
422  double lambda=1.0; // Start out with full Newton step
423  double lambda_temp,lambda2=lambda;
424  DMatrix3x1 newF;
425  double f2=0.,newf;
426 
427  // Compute starting values for f=1/2 F.F
428  double f=-0.5*slope;
429 
430  for (;;){
431  newpar=par+lambda*fullstep;
432 
433  // Compute the value of the vector F and f=1/2 F.F with the current step
434  for (int i=0;i<3;i++){
435  double dx=(newpar(X0)-X(i))*ONE_OVER_H;
436  double argp=newpar(K2)*(dx+A_OVER_H);
437  double argm=newpar(K2)*(dx-A_OVER_H);
438  newF(i)=N(i)-0.25*newpar(QA)*(tanh(argp)-tanh(argm));
439  }
440  newf=0.5*newF.Mag2(); // dot product
441 
442  if (lambda<0.1) { // make sure the step is not too small
443  newpar=par;
444  return NOERROR;
445  } // Check if we have sufficient function decrease
446  else if (newf<=f+ALPHA*lambda*slope){
447  return NOERROR;
448  }
449  else{
450  // g(lambda)=f(par+lambda*fullstep)
451  if (lambda==1.0){//first attempt: quadratic approximation for g(lambda)
452  lambda_temp=-0.5*slope/(newf-f-slope);
453  }
454  else{ // cubic approximation for g(lambda)
455  double temp1=newf-f-lambda*slope;
456  double temp2=f2-f-lambda2*slope;
457  double one_over_lambda2_sq=1./(lambda2*lambda2);
458  double one_over_lambda_sq=1./(lambda*lambda);
459  double one_over_lambda_diff=1./(lambda-lambda2);
460  double a=(temp1*one_over_lambda_sq-temp2*one_over_lambda2_sq)*one_over_lambda_diff;
461  double b=(-lambda2*temp1*one_over_lambda_sq+lambda*temp2*one_over_lambda2_sq)
462  *one_over_lambda_diff;
463  if (a==0.0) lambda_temp=-0.5*slope/b;
464  else{
465  double disc=b*b-3.0*a*slope;
466  if (disc<0.0) lambda_temp=0.5*lambda;
467  else if (b<=0.0) lambda_temp=(-b+sqrt(disc))/(3.*a);
468  else lambda_temp=-slope/(b+sqrt(disc));
469  }
470  // ensure that we are headed in the right direction...
471  if (lambda_temp>0.5*lambda) lambda_temp=0.5*lambda;
472  }
473  }
474  lambda2=lambda;
475  f2=newf;
476  // Make sure that new version of lambda is not too small
477  lambda=(lambda_temp>0.1*lambda ? lambda_temp : 0.1*lambda);
478  }
479  }
480 
481 };
482 
483 #endif //DFDCPSEUDO_H
#define F(x, y, z)
DVector2 xy
rough x,y coordinates in lab coordinate system
Definition: DFDCPseudo.h:100
DMatrix3x3 Invert() const
Definition: DMatrix3x3.h:90
double q
&lt; energy deposition, from pulse height
Definition: DFDCPseudo.h:98
#define A_OVER_H
#define X0
TVector2 DVector2
Definition: DVector2.h:9
#define TOLX
int status
status word for pseudopoint
Definition: DFDCPseudo.h:94
#define QA
double t_v
time of the two cathode clusters
Definition: DFDCPseudo.h:86
#define ONE_OVER_H
const DFDCWire * wire
DFDCWire for this wire.
Definition: DFDCPseudo.h:92
double q_from_pulse_height
Definition: DFDCPseudo.h:25
class DFDCPseudo: definition for a reconstructed point in the FDC
Definition: DFDCPseudo.h:74
vector< double > GetFDCPseudoAlignmentDerivatives()
Definition: DFDCPseudo.h:125
static char index(char c)
Definition: base64.cpp:115
#define X(str)
Definition: hddm-c.cpp:83
#define TOLF
double phi_v
rotation angles for cathode planes
Definition: DFDCPseudo.h:87
TF1 * f
Definition: FitGains.C:21
double w_c
Definition: DFDCPseudo.h:90
FDCPseudoD
Definition: DFDCPseudo.h:56
double pos
Definition: DFDCPseudo.h:23
int itrack
Definition: DFDCPseudo.h:99
TEllipse * e
DFDCPseudo()
DANA identifier.
Definition: DFDCPseudo.h:82
centroid_t cluster_v
Cathode cluster centroids, Useful for gain/strip pitch calibration.
Definition: DFDCPseudo.h:88
vector< double > GetFDCStripGainDerivatives()
Definition: DFDCPseudo.h:160
FDCTrackD
Definition: DFDCPseudo.h:33
double q
Definition: DFDCPseudo.h:24
DMatrix3x1 X
Definition: DFDCPseudo.h:30
double dE
energy deposition, from integral
Definition: DFDCPseudo.h:96
double s
&lt; wire position computed from cathode data, assuming the avalanche occurs at the wire ...
Definition: DFDCPseudo.h:91
#define K2
double t_rms
Definition: DFDCPseudo.h:28
double Mag2() const
Definition: DMatrix3x1.h:57
int numstrips
Definition: DFDCPseudo.h:26
jerror_t FindNewParmVec(const DMatrix3x1 &N, const DMatrix3x1 &X, const DMatrix3x1 &F, const DMatrix3x3 &J, const DMatrix3x1 &par, DMatrix3x1 &newpar)
Definition: DFDCPseudo.h:394
double covyy
Covariance terms for (x,y)
Definition: DFDCPseudo.h:95
double dE_amp
Definition: DFDCPseudo.h:97
double w
Definition: DFDCPseudo.h:89
double time
time corresponding to this pseudopoint.
Definition: DFDCPseudo.h:93
double t
Definition: DFDCPseudo.h:27
double sqrt(double)
double sin(double)
void toStrings(vector< pair< string, string > > &items) const
Definition: DFDCPseudo.h:102
const vector< double > GetFDCStripPitchDerivatives()
Definition: DFDCPseudo.h:207
#define ITER_MAX
TF1 * f2
Definition: FitGains.C:28
unsigned int cluster
Definition: DFDCPseudo.h:29
jerror_t FindCentroid(DMatrix3x1 N, DMatrix3x1 X, double &pos)
Definition: DFDCPseudo.h:317
double v
centroid positions in the two cathode views
Definition: DFDCPseudo.h:85
union @6::@8 u
#define ALPHA