00001
00002
00003
00004
00005
00006
00007 #include "Alignment/AlignTPCDrift2.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 "Geometry/GTPCGeo.h"
00015 #include "RecoBase/RBKTrack.h"
00016 #include "RecoBase/RBKVertex.h"
00017 #include "RecoBase/RBViewHit.h"
00018 #include "Swimmer/SwimDrift.h"
00019 #include "Swimmer/SwimDriftMap.h"
00020 #include "Swimmer/SwimMIPP.h"
00021 #include "TPCRecoJP/TPCRHit.h"
00022 #include "TrkRBase/TrkRUtil.h"
00023
00024 #include <TMinuit.h>
00025 #include <cmath>
00026
00027 MODULE_DECL(AlignTPCDrift2);
00028
00029 using namespace std;
00030
00031 AlignTPCDrift2* AlignTPCDrift2::gModule = 0;
00032
00033
00034
00035 AlignTPCDrift2::AlignTPCDrift2(const char* version) :
00036 JobCModule("AlignTPCDrift2")
00037 {
00038
00039 SetCfgVersion(version);
00040
00041 CheckInit();
00042 }
00043
00044
00045
00046 AlignTPCDrift2::~AlignTPCDrift2()
00047 {
00048 }
00049
00050
00051
00052 JobCResult AlignTPCDrift2::Ana(const EDMEventHandle& evt)
00053 {
00054 vector<const RBKVertex*> vtx(0);
00055
00056 evt.Cal();
00057 try { evt.Reco().Get(fFolder.c_str(), vtx); }
00058 catch (...) { return kFailed; }
00059 if (vtx.empty()) { return kFailed;}
00060
00061 TrkInfo_t ti;
00062 ti.fSwim = 0;
00063 GTPCGeo& tpcgeo = GMIPPGeo::Instance().TPC();
00064
00065 int nGood = 0;
00066 for (unsigned int i = 0; i < vtx.size(); ++i) {
00067 const RBKVertex* v = vtx[i];
00068 if (fRequireBeamTrk && !v->InTrack()) continue;
00069 int nTrk = v->NTracks() + (v->InTrack() ? 1 : 0);
00070 if (nTrk < fMinTrkVtx) continue;
00071
00072 for (int j = 0; j < v->NTracks(); ++j) {
00073 const RBKTrack* t = v->OutTrack(j);
00074
00075 if (t->NSpacePoints() < fMinTPCHits ||
00076 t->NSpacePoints() > fMaxTPCHits ||
00077 t->NViewHits() < fMinChamHits ||
00078 fabs(t->QoP()) > fMinP ||
00079 t->Time() < fMinTrkTime ||
00080 t->Time() > fMaxTrkTime ||
00081 t->GoF() < fMinGoF ||
00082 fabs(t->QoP()) < 5e-3) {
00083 if (fDebug) {
00084 cout << "Skipping track: nSpacePts=" << t->NSpacePoints()
00085 << " nViewHits=" << t->NViewHits()
00086 << " QoP=" << t->QoP()
00087 << " T=" << t->Time()
00088 << " GoF=" << t->GoF()
00089 << endl;
00090 }
00091 continue;
00092 }
00093
00094 ti.fNTPCHit = t->NSpacePoints();
00095 if (ti.fNTPCHit > 128) ti.fNTPCHit = 128;
00096 for (int j = 0; j < ti.fNTPCHit; ++j) {
00097 const TPCRHit* hit =
00098 & dynamic_cast<const TPCRHit&>(t->SpacePoint(j));
00099 assert (hit);
00100 ti.fPadX[j] = tpcgeo.PadColToX(hit->PadCol());
00101 ti.fPadZ[j] = tpcgeo.PadRowToZ(hit->PadRow());
00102 ti.fDriftT[j] = hit->TDC() * GTPCGeo::kUsecPerBucket +
00103 tpcgeo.TOffset();
00104 }
00105
00106 ti.fNChamHit = t->NViewHits();
00107 if (ti.fNChamHit > 36) ti.fNChamHit = 36;
00108 for (int j = 0; j < ti.fNChamHit; ++j) {
00109 const RBViewHit& hit = t->ViewHit(j);
00110 ti.fChamZ[j] = hit.Z();
00111 ti.fU[j] = hit.U();
00112 ti.fW[j] = 1 / (hit.USig() * hit.USig());
00113 ti.fCosA[j] = hit.CosTheta();
00114 ti.fSinA[j] = hit.SinTheta();
00115 }
00116 ti.fZ0 = t->VtxZ();
00117 ti.fPar[0] = t->VtxX();
00118 ti.fPar[1] = t->VtxY();
00119 ti.fPar[2] = t->VtxDXDZ();
00120 ti.fPar[3] = t->VtxDYDZ();
00121 ti.fPar[4] = t->QoP();
00122
00123 double chi2 = ComputeTrkChi2(ti);
00124 if (chi2 > 1e6) continue;
00125
00126 if (fDebug) {
00127 printf("Using track: N=%d/%d q/p=%.1e vtx=(%.1f,%.1f;%.1e,%.1e) chi2=%.1f\n",
00128 t->NSpacePoints(), t->NViewHits(), t->QoP(),
00129 t->VtxX(), t->VtxY(), t->VtxDXDZ(), t->VtxDYDZ(),
00130 t->Chi2());
00131 printf("My fit: q/p=%.1e vtx=(%.1f,%.1f;%.1e,%.1e) chi2=%.1f\n",
00132 ti.fPar[4], ti.fPar[0], ti.fPar[1], ti.fPar[2], ti.fPar[3],
00133 chi2);
00134 }
00135
00136
00137 fTrkInfo.push_back(ti);
00138 ++nGood;
00139 }
00140 }
00141
00142 if (fDebug) cout << " picked " << nGood << " tracks" << endl;
00143
00144 return (nGood > 0);
00145 }
00146
00147
00148
00149 void AlignTPCDrift2::NewRun(int run, int subrun)
00150 {
00151 GMIPPGeo::Instance(run);
00152 config_bfield(run, subrun);
00153 SwimDriftMap::Instance().Init(run);
00154 SwimDrift::Instance().SetUseDriftMap(1);
00155 }
00156
00157
00158
00159 void AlignTPCDrift2::EndRun(int , int )
00160 {
00161 if (fTrkInfo.size() < 1) {
00162 cout << "Can't do minimization with " << fTrkInfo.size() << " tracks"
00163 << endl;
00164 return;
00165 }
00166 cout << "AlignTPCDrift2: doing minimization with " << fTrkInfo.size()
00167 << " tracks" << endl;
00168 gModule = this;
00169
00170 TMinuit* minu = new TMinuit(7);
00171 minu->SetMaxIterations(1000000);
00172 minu->SetFCN(AlignTPCDrift2::MinFCN);
00173 char name[32];
00174 for (int i = 0; i < 3; ++i) {
00175 sprintf(name, "V%c Scale", 'x' + i);
00176 minu->DefineParameter(i, name, 1, 0.01, 0.1, 3);
00177 }
00178 for (int i = 0; i < 3; ++i) {
00179 sprintf(name, "V%c LinScale", 'x' + i);
00180 minu->DefineParameter(i + 3, name, 0, 0.01, -1, 1);
00181 }
00182 minu->DefineParameter(6, "Bx Bz rotation", 0.007, 1e-3, -2e-2, 2e-2);
00183
00184 for (unsigned int i = 0; i < fFixParam.size(); ++i)
00185 minu->FixParameter(fFixParam[i]);
00186
00187 minu->Migrad();
00188
00189 delete minu;
00190 }
00191
00192
00193
00194 void AlignTPCDrift2::MinFCN(int& , double* , double& f,
00195 double* par, int )
00196 {
00197 SwimDriftMap::Instance().SetScale(par[0], par[1], par[2],
00198 par[3], par[4], par[5]);
00199 SwimDriftMap::Instance().SetBxBzRotation(par[6]);
00200
00201 f = 0;
00202 for (unsigned int i = 0; i < gModule->fTrkInfo.size(); ++i)
00203 f += gModule->ComputeTrkChi2(gModule->fTrkInfo[i]);
00204
00205 cout << "par=(" << par[0] << ", " << par[1] << ", " << par[2]
00206 << "; " << par[3] << ", " << par[4] << ", " << par[5]
00207 << ", " << par[6] << ") f=" << f << endl;
00208
00209 }
00210
00211
00212
00213 void AlignTPCDrift2::Update(const CfgConfig& c)
00214 {
00215 c("Debug").Get(fDebug);
00216 c("Folder").Get(fFolder);
00217 fFixParam.clear();
00218 try { c("FixParam").Get(fFixParam); }
00219 catch (...) {
00220 int val;
00221 c("FixParam").Get(val);
00222 fFixParam.push_back(val);
00223 }
00224 c("MinTrkVtx").Get(fMinTrkVtx);
00225 c("RequireBeamTrk").Get(fRequireBeamTrk);
00226 c("MinTPCHits").Get(fMinTPCHits);
00227 c("MaxTPCHits").Get(fMaxTPCHits);
00228 c("MinChamHits").Get(fMinChamHits);
00229 c("MinP").Get(fMinP);
00230 fMinP = (fMinP > 0) ? 1 / fMinP : 1e6;
00231 c("MinGoF").Get(fMinGoF);
00232 c("TPCSigmaX").Get(fTPCSigmaX);
00233 fTPCSigmaX = 1 / (fTPCSigmaX * fTPCSigmaX);
00234 c("TPCSigmaY").Get(fTPCSigmaY);
00235 fTPCSigmaX = 1 / (fTPCSigmaY * fTPCSigmaY);
00236
00237 c("MinTrkTime").Get(fMinTrkTime);
00238 c("MaxTrkTime").Get(fMaxTrkTime);
00239
00240
00241 fIsInit = true;
00242 }
00243
00244
00245
00246 double AlignTPCDrift2::ComputeTrkChi2(TrkInfo_t& ti)
00247 {
00248 double u[512];
00249 double w[512];
00250 double z[512];
00251 double cosA[512];
00252 double sinA[512];
00253 double lamX[512];
00254 double lamY[512];
00255
00256 if (!ti.fSwim) {
00257 ti.fSwim = new SwimMIPP;
00258 ti.fSwim->Swim(ti.fZ0, ti.fPar);
00259 }
00260 double p = 1 / ti.fPar[4];
00261
00262 double padPos[3];
00263 double cavePos[3];
00264 double hitPos[3];
00265 SwimDrift& drift = SwimDrift::Instance();
00266 GTPCGeo& tpcgeo = GMIPPGeo::Instance().TPC();
00267
00268 for (int i = 0; i < ti.fNTPCHit; ++i) {
00269
00270 padPos[0] = ti.fPadX[i];
00271 padPos[1] = 0;
00272 padPos[2] = ti.fPadZ[i];
00273 tpcgeo.PPLNToCAVE(padPos, cavePos);
00274
00275
00276 drift.CorrectDistortion(cavePos, hitPos, ti.fDriftT[i]);
00277
00278 z[i * 2 + 1] = z[i * 2] = hitPos[2];
00279 u[i * 2] = hitPos[0];
00280 u[i * 2 + 1] = hitPos[1];
00281 w[i * 2] = fTPCSigmaX;
00282 w[i * 2 + 1] = fTPCSigmaY;
00283
00284
00285 if (!ti.fSwim->GetXY(hitPos[2], &hitPos[0], &hitPos[1])) return 1e6;
00286 lamX[i * 2 + 1] = lamX[i * 2] =
00287 p * (hitPos[0] - ti.fPar[0] - ti.fPar[2] * (hitPos[2] - ti.fZ0));
00288 lamY[i * 2 + 1] = lamY[i * 2] =
00289 p * (hitPos[1] - ti.fPar[1] - ti.fPar[3] * (hitPos[2] - ti.fZ0));
00290
00291 cosA[i * 2] = 1;
00292 sinA[i * 2] = 0;
00293 cosA[i * 2 + 1] = 0;
00294 sinA[i * 2 + 1] = -1;
00295 }
00296
00297
00298 int i = ti.fNTPCHit * 2;
00299 for (int j = 0; j < ti.fNChamHit; ++i, ++j) {
00300 u[i] = ti.fU[j];
00301 w[i] = ti.fW[j];
00302 cosA[i] = ti.fCosA[j];
00303 sinA[i] = ti.fSinA[j];
00304 z[i] = ti.fChamZ[j];
00305 if (!ti.fSwim->GetXY(z[i], &hitPos[0], &hitPos[1])) return 1e6;
00306 lamX[i] =
00307 p * (hitPos[0] - ti.fPar[0] - ti.fPar[2] * (z[i] - ti.fZ0));
00308 lamY[i] =
00309 p * (hitPos[1] - ti.fPar[1] - ti.fPar[3] * (z[i] - ti.fZ0));
00310 }
00311
00312
00313
00314
00315
00316
00317 double par[5];
00318 double chi2 =
00319 TrkRUtil::FitCurvedTrack(i, u, w, z, cosA, sinA, ti.fZ0, lamX, lamY,
00320 par, 0);
00321
00322
00323 SwimMIPP swim;
00324 swim.Swim(ti.fZ0, par);
00325 p = 1 / par[4];
00326
00327 for (int j = 0; j < i; ++j) {
00328 if (!ti.fSwim->GetXY(z[i], &hitPos[0], &hitPos[1])) return 1e6;
00329 lamX[i] =
00330 p * (hitPos[0] - ti.fPar[0] - ti.fPar[2] * (z[i] - ti.fZ0));
00331 lamY[i] =
00332 p * (hitPos[1] - ti.fPar[1] - ti.fPar[3] * (z[i] - ti.fZ0));
00333 }
00334
00335
00336 chi2 =
00337 TrkRUtil::FitCurvedTrack(i, u, w, z, cosA, sinA, ti.fZ0, lamX, lamY,
00338 par, 0);
00339
00340 return chi2;
00341 }
00342
00343