AlignChamZ.cxx

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////
00002 // $Id: AlignChamZ.cxx,v 1.4 2007/02/20 02:38:06 lebedev Exp $
00003 //
00004 // lebedev@physics.harvard.edu
00005 ////////////////////////////////////////////////////////////////////////
00006 
00007 #include "Alignment/AlignChamZ.h"
00008 
00009 #include "Bfield/bfield.h"
00010 #include "Bfield/BFMagnet.h"
00011 #include "Config/CfgConfig.h"
00012 #include "Config/CfgParam.h"
00013 #include "EventDataModel/EDMEventHandle.h"
00014 #include "TrkRBase/TrkChamGeo.h"
00015 #include "TrkRBase/TrkCand.h"
00016 #include "TrkRBase/WireClust.h"
00017 #include "TrkRBase/TrkRUtil.h"
00018 
00019 #include <TMinuit.h>
00020 #include <TTree.h>
00021 
00022 #include <cmath>
00023 #include <cassert>
00024 #include <iostream>
00025 
00026 MODULE_DECL(AlignChamZ);
00027 
00028 using namespace std;
00029 using namespace TrkRUtil;
00030 
00031 static AlignChamZ* gModule;
00032 
00033 //......................................................................
00034 
00035 AlignChamZ::AlignChamZ(const char* version) :
00036   JobCModule("AlignChamZ")
00037 {
00038   // Register module to be updated with a given config version
00039   SetCfgVersion(version);
00040   // Make sure that configuration has been loaded
00041   CheckInit();
00042 }
00043 
00044 //......................................................................
00045 
00046 AlignChamZ::~AlignChamZ()
00047 {
00048 }
00049 
00050 //......................................................................
00051 
00052 JobCResult AlignChamZ::Ana(const EDMEventHandle& evt)
00053 {
00054   vector<const TrkCand*> vec(0);
00055 
00056   try { evt.Reco().Get(fFolder.c_str(), vec); }
00057   catch (...) { return kFailed; }
00058 
00059   TrkInfo_t ti;
00060 
00061   for (unsigned int i = 0; i < vec.size(); ++i) {
00062     const TrkCand* trk = vec[i];
00063 
00064     memset(&ti, 0, sizeof(TrkInfo_t));
00065 
00066     int nClu = 0;
00067     for (int j = 0; j < trk->NClust(); ++j) {
00068       const WireClust* wc = trk->Clust(j);
00069       int cham = wc->Chamber();
00070       int p = wc->Plane() - 1;
00071 
00072       if (cham > kBC3) nClu++;
00073 
00074       ti.fWire[cham][p] = wc->AvgWire();
00075       ti.fWeight[cham][p] = 1.0 / (wc->USig() * wc->USig());
00076     }
00077     if (nClu < fMinNClust) continue;
00078     fTrackList.push_back(ti);
00079   }
00080 
00081   return kPassed;
00082 }
00083 
00084 //......................................................................
00085   
00086 void AlignChamZ::NewRun(int run, int subrun)
00087 {
00088   GMIPPGeo::Instance(run);
00089   config_bfield(run, subrun);
00090   if (fLoadAlignment) TrkChamGeo::Instance().Init(run);
00091   fZ0 = GMIPPGeo::Instance().Cham(kDC1).ZGas() - 20;
00092 }
00093 
00094 //......................................................................
00095 
00096 double AlignChamZ::ComputeF()
00097 {
00098   CalcLambda(fZ0, fLambdaX, fLambdaY);
00099   
00100   if (fUseCorr) return ComputeCorrF();
00101   else return ComputeChi2F();
00102 }
00103 
00104 //......................................................................
00105 
00106 double AlignChamZ::ComputeChi2F()
00107 {
00108   double u[kNCham * kNPlane];
00109   double w[kNCham * kNPlane];
00110   double z[kNCham * kNPlane];
00111   double cosA[kNCham * kNPlane];
00112   double sinA[kNCham * kNPlane];
00113   double lambdaX[kNCham * kNPlane];
00114   double lambdaY[kNCham * kNPlane];
00115   int chamber[kNCham * kNPlane];
00116 
00117   double f = 0;
00118   for (unsigned int i = 0; i < fTrackList.size(); ++i) {
00119     TrkInfo_t& ti = fTrackList[i];
00120 
00121     int nClust = 0;
00122     for (int cham = 0; cham < kNCham; ++cham) {
00123       GChamGeo& geo = GMIPPGeo::Instance().Cham(cham);
00124       for (int p = 0; p < kNPlane; ++p) {
00125     if (ti.fWeight[cham][p] < 1e-3) continue;
00126     geo.WireToU(p + 1, ti.fWire[cham][p], u[nClust]);
00127     w[nClust] = ti.fWeight[cham][p];
00128     z[nClust] = geo.Z(p + 1);
00129     cosA[nClust] = geo.GAngleCos(p + 1);
00130     sinA[nClust] = geo.GAngleSin(p + 1);
00131     lambdaX[nClust] = fLambdaX[cham][p];
00132     lambdaY[nClust] = fLambdaY[cham][p];
00133     chamber[nClust] = cham * kNPlane + p;
00134     nClust++;
00135       }
00136     }
00137 
00138     double par[5];
00139     FitCurvedTrack(nClust, u, w, z, cosA, sinA, fZ0, lambdaX, lambdaY,
00140            par, 0);
00141     
00142     // Reinitialize lambda's based on the first-try fit
00143     double lx[kNCham][kNPlane], ly[kNCham][kNPlane];
00144     CalcLambda(fZ0, lx, ly, par);
00145     for (int i = 0; i < nClust; ++i) {
00146       int cham =chamber[i] / kNPlane;
00147       int pl = chamber[i] % kNPlane;
00148       lambdaX[i] = lx[cham][pl];
00149       lambdaY[i] = ly[cham][pl];
00150     }
00151     double chi2 = FitCurvedTrack(nClust, u, w, z, cosA, sinA, fZ0, 
00152                  lambdaX, lambdaY, par, 0);
00153     if (chi2 < 1e5) f += chi2;
00154     else {
00155       cout << "Failed fit?: chi2=" << chi2 << " (" 
00156        <<  par[0] << ", " << par[1]
00157        << "; " << par[2] << ", " << par[3] << "; " << par[4]
00158        << endl;
00159     }
00160   }
00161   return f;
00162 }
00163 
00164 //......................................................................
00165 
00166 double AlignChamZ::ComputeCorrF()
00167 {
00168   double resid[kNCham][kNPlane];
00169   int n[kNCham][kNPlane];
00170   double x[kNCham][kNPlane];
00171   double y[kNCham][kNPlane];
00172   double xx[kNCham][kNPlane];
00173   double yy[kNCham][kNPlane];
00174   double xy[kNCham][kNPlane];
00175   memset(x, 0, sizeof(x));
00176   memset(n, 0, sizeof(n));
00177   memset(y, 0, sizeof(y));
00178   memset(xx, 0, sizeof(xx));
00179   memset(yy, 0, sizeof(yy));
00180   memset(xy, 0, sizeof(xy));
00181 
00182   double dxdz[kNCham];
00183 
00184   for (unsigned int i = 0; i < fTrackList.size(); ++i) {
00185     TrkInfo_t& ti = fTrackList[i];
00186     
00187     Fit(ti, resid, dxdz);
00188 
00189     for (int c = kDC1; c < kNCham; ++c) {
00190       for (int p = 0; p < kNPlane; ++p) {
00191     if (ti.fWeight[c][p] < 1) continue;
00192     n[c][p]++;
00193     x[c][p] += dxdz[c];
00194     xx[c][p] += dxdz[c] * dxdz[c];
00195     y[c][p] += resid[c][p];
00196     yy[c][p] += resid[c][p] * resid[c][p];
00197     xy[c][p] += dxdz[c] * resid[c][p];
00198       }
00199     }
00200   }
00201 
00202   double f = 0;
00203   for (int c = kDC1; c < kNCham; ++c) {
00204     for (int p = 0; p < kNPlane; ++p) {
00205       if (n[c][p] < 10) continue;
00206       
00207       // Add square of correlation coefficient for this plane
00208       double corr = (n[c][p] * xy[c][p] - x[c][p] * y[c][p]);
00209       corr *= corr;
00210       corr /= (n[c][p] * xx[c][p] - x[c][p] * x[c][p]) *
00211     (n[c][p] * yy[c][p] - y[c][p] * y[c][p]);
00212       assert(fabs(corr) < 1);
00213 
00214       //cout << "Correlation coeff for " << c << p << ": " << corr << endl;
00215       
00216       f += corr;
00217     }
00218   }
00219   return f;
00220 }
00221 
00222 //......................................................................
00223 
00224 double AlignChamZ::Fit(const TrkInfo_t& ti, double resid[kNCham][kNPlane],
00225               double dxdz[kNCham])
00226 {
00227   int nClust = 0;
00228   double u[kNCham * kNPlane];
00229   double w[kNCham * kNPlane];
00230   double z[kNCham * kNPlane];
00231   double cosA[kNCham * kNPlane];
00232   double sinA[kNCham * kNPlane];
00233   double lambdaX[kNCham * kNPlane];
00234   double lambdaY[kNCham * kNPlane];
00235   short chamber[kNCham * kNPlane];
00236   
00237   for (int cham = 0; cham < kNCham; ++cham) {
00238     GChamGeo& geo = GMIPPGeo::Instance().Cham(cham);
00239     for (int p = 0; p < kNPlane; ++p) {
00240       resid[cham][p] = 0;
00241       if (ti.fWeight[cham][p] < 1e-3) continue;
00242       geo.WireToU(p + 1, ti.fWire[cham][p], u[nClust]);
00243       w[nClust] = ti.fWeight[cham][p];
00244       z[nClust] = geo.Z(p + 1);
00245       cosA[nClust] = geo.GAngleCos(p + 1);
00246       sinA[nClust] = geo.GAngleSin(p + 1);
00247       lambdaX[nClust] = fLambdaX[cham][p];
00248       lambdaY[nClust] = fLambdaY[cham][p];
00249       chamber[nClust] = cham * kNPlane + p;
00250       nClust++;
00251     }
00252   }
00253 
00254   double par[5];
00255   FitCurvedTrack(nClust, u, w, z, cosA, sinA, fZ0, lambdaX, lambdaY,
00256                  par, 0);
00257 
00258   // Reinitialize lambda's based on the first-try fit
00259   double lx[kNCham][kNPlane], ly[kNCham][kNPlane];
00260   CalcLambda(fZ0, lx, ly, par);
00261   for (int i = 0; i < nClust; ++i) {
00262     int cham =chamber[i] / kNPlane;
00263     int pl = chamber[i] % kNPlane;
00264     lambdaX[i] = lx[cham][pl];
00265     lambdaY[i] = ly[cham][pl];
00266   }
00267   FitCurvedTrack(nClust, u, w, z, cosA, sinA, fZ0, lambdaX, lambdaY,
00268                  par, 0);
00269   double mom = par[4];
00270   SwimMIPP swim;
00271   swim.Swim(fZ0, par);
00272   for (int c = kDC1; c < kNCham; ++c) {
00273     double p[3];
00274     swim.GetPatZ(GMIPPGeo::Instance().Cham(c).ZGas(), p);
00275     dxdz[c] = p[0] / p[2];
00276   }
00277 
00278   // Loop through every cluster, exclude it from the fit and compute
00279   // residual
00280   for (int i = 0; i < nClust; ++i) {
00281     double saveW = w[i];
00282     w[i] = 0;
00283     FitCurvedTrack(nClust, u, w, z, cosA, sinA, fZ0, lambdaX, lambdaY,
00284            par, 0);
00285     w[i] = saveW;
00286 
00287     int c = chamber[i] / kNPlane;
00288     int p = chamber[i] % kNPlane;
00289     GChamGeo& geo = GMIPPGeo::Instance().Cham(c);
00290 
00291     double dz = geo.Z(p + 1) - fZ0;
00292     double x = par[0] + dz * par[2] + par[4] * lambdaX[i];
00293     double y = par[1] + dz * par[3] + par[4] * lambdaY[i];
00294     double ufit;
00295     geo.XYToU(p + 1, x, y, ufit);
00296     resid[c][p] = ufit - u[i];
00297   }
00298 
00299   return mom;
00300 }
00301 
00302 //......................................................................
00303 
00304 static void gsFCN(int& /*npar*/, double* /*gin*/, double& f,
00305                   double* par, int /*iflag*/)
00306 {
00307   for (int i = 0; i < 12; ++i) {
00308     if (!isnormal(par[i]) && par[i] != 0) {
00309       f = 0;
00310       cout << "Abnormal parameters in TMinuit" << endl;
00311       return;
00312     }
00313   }
00314   cout << "Minimizing with " << par[7] << endl;
00315 
00316   // Setup geometry based on the new constants
00317   for (int i = 0; i < 6; ++i) {
00318     GMIPPGeo::Instance().Cham(i + kDC1).SetZGas(par[i]);
00319   }
00320   BFMagnet::JGG().SetCenterPos(par[6], par[7], par[8]);
00321   BFMagnet::Rosie().SetCenterPos(par[9], par[10], par[11]);
00322   
00323   // Compute the function we want to minimize
00324   f = gModule->ComputeF();
00325 }
00326 
00327 //......................................................................
00328 
00329 void AlignChamZ::EndRun(int /*run*/, int /* subrun */)
00330 {
00331   if (fTrackList.size() < 100) {
00332     cout << "Can't do minimization with less than 100 tracks!" << endl;
00333     return;
00334   }
00335 
00336   cout << "Doing minimization with " << fTrackList.size() << " tracks"
00337        << endl;
00338 
00339   double lx[9][4], ly[9][4];
00340   CalcLambda(fZ0, lx, ly);
00341   for (int i = kDC1; i < 9; ++i) {
00342     cout << "Lambda X " << GChamGeo::Name(i) << ":";
00343     for (int j = 0; j < 4; ++j) cout << lx[i][j] << " ";
00344     cout << "\nLambda Y " << GChamGeo::Name(i) << ":";
00345     for (int j = 0; j < 4; ++j) cout << ly[i][j] << " ";
00346     cout << endl;
00347   }
00348 
00349   gModule = this;
00350   
00351   TMinuit minu(12);
00352   minu.SetFCN(gsFCN);
00353 
00354   char name[256];
00355   int ierr;
00356   double saveZ[6];
00357   for (int i = 0; i < 6; ++i) {
00358     GChamGeo& geo = GMIPPGeo::Instance().Cham(i + kDC1);
00359     sprintf(name, "%s_z", geo.Name());
00360     minu.mnparm(i, name, geo.ZGas(), 0.1, 
00361         geo.ZGas() - 10, geo.ZGas() + 10, ierr);
00362     saveZ[i] = geo.ZGas();
00363   }
00364   BFMagnet& jgg = BFMagnet::JGG();
00365   minu.mnparm(6, "JGGX", jgg.CenterPos()[0], 1, 0, 0, ierr);
00366   minu.mnparm(7, "JGGY", jgg.CenterPos()[1], 1, 0, 0, ierr);
00367   minu.mnparm(8, "JGGZ", jgg.CenterPos()[2], 1, 0, 0, ierr);
00368 
00369   BFMagnet& rosie = BFMagnet::Rosie();
00370   minu.mnparm(9, "RosieX", rosie.CenterPos()[0], 1, 0, 0, ierr);
00371   minu.mnparm(10, "RosieY", rosie.CenterPos()[1], 1, 0, 0, ierr);
00372   minu.mnparm(11, "RosieZ", rosie.CenterPos()[2], 1, 0, 0, ierr);
00373 
00374   for (unsigned int i = 0; i < fFixParam.size(); ++i) 
00375     minu.FixParameter(fFixParam[i]);
00376 
00377   minu.Migrad();
00378 
00379   MakeTree();
00380 
00381   for (int i = 0; i < 6; ++i) {
00382     double par, perr;
00383     minu.GetParameter(i, par, perr);
00384     cout << GChamGeo::Name(i + kDC1) << " z shift: " 
00385      << par - saveZ[i] << " err: " << perr << endl;
00386   }
00387 }
00388 
00389 //......................................................................
00390 
00391 void AlignChamZ::MakeTree()
00392 {
00393   double mom;
00394   double resid[kNCham][kNPlane];
00395   double  u[kNCham][kNPlane];
00396   double dxdz[kNCham];
00397 
00398   TTree* tree = new TTree("altree", "Post-alignment residuals");
00399   tree->Branch("mom", &mom, "mom/D");
00400   tree->Branch("resid", &resid, "resid[9][4]/D");
00401   tree->Branch("u", &u, "u[9][4]/D");
00402   tree->Branch("dxdz", &dxdz, "dxdz[9]/D");
00403 
00404   for (unsigned int i = 0; i < fTrackList.size(); ++i) {
00405     TrkInfo_t& ti = fTrackList[i];
00406 
00407     mom = Fit(ti, resid, dxdz);
00408     for (int c = 0; c < kNCham; ++c) {
00409       GChamGeo& geo = GMIPPGeo::Instance().Cham(c);
00410       for (int p = 0; p < kNPlane; ++p) {
00411     if (ti.fWeight[c][p] < 1e-3) u[c][p] = 1e6;
00412     else geo.WireToU(p + 1, ti.fWire[c][p], u[c][p]);
00413       }
00414     }
00415     tree->Fill();
00416   }
00417 
00418   tree->Write();
00419   delete tree;
00420 }
00421 
00422 //......................................................................
00423 
00424 void AlignChamZ::Update(const CfgConfig& c)
00425 {
00426   c("Debug").Get(fDebug);
00427   c("Folder").Get(fFolder);
00428   c("LoadAlignment").Get(fLoadAlignment);
00429   c("MinNClust").Get(fMinNClust);
00430   fFixParam.clear();
00431   try { c("FixParam").Get(fFixParam); }
00432   catch (...) {
00433     int i;
00434     c("FixParam").Get(i);
00435     fFixParam.push_back(i);
00436   }
00437   c("UseCorr").Get(fUseCorr);
00438 
00439   // Change the flag to signify that our configuration has been read
00440   fIsInit = true;
00441 }
00442 
00443 ////////////////////////////////////////////////////////////////////////

Generated on Mon Nov 23 08:01:43 2009 for MIPP(E907) by  doxygen 1.4.7