00001
00002
00003
00004
00005
00006
00007 #include "Alignment/AlignChamZNoBF.h"
00008
00009 #include "Config/CfgConfig.h"
00010 #include "Config/CfgParam.h"
00011 #include "EventDataModel/EDMEventHandle.h"
00012 #include "TrkRBase/TrackSeg.h"
00013 #include "TrkRBase/TrkRUtil.h"
00014
00015 #include <TMinuit.h>
00016 #include <TTree.h>
00017
00018 #include <iostream>
00019 #include <cmath>
00020
00021 MODULE_DECL(AlignChamZNoBF);
00022 using namespace std;
00023
00024 static AlignChamZNoBF* gModule = 0;
00025
00026
00027
00028 AlignChamZNoBF::AlignChamZNoBF(const char* version) :
00029 JobCModule("AlignChamZNoBF")
00030 {
00031
00032 SetCfgVersion(version);
00033
00034 CheckInit();
00035 }
00036
00037
00038
00039 AlignChamZNoBF::~AlignChamZNoBF()
00040 {
00041 }
00042
00043
00044
00045 JobCResult AlignChamZNoBF::Ana(const EDMEventHandle& evt)
00046 {
00047 evt.Raw();
00048 evt.Cal();
00049 std::vector<const TrackSeg*> seg(0);
00050 try {
00051 evt.Reco().Get(fSegFolder.c_str(), seg);
00052 if (seg.empty()) return kFailed;
00053 if (fDebug) cout << "Got " << seg.size() << " tracks" << endl;
00054 }
00055 catch (...) { return kFailed; }
00056
00057 TrkInfo_t ti;
00058 double resid[6][4];
00059
00060 for (unsigned int i = 0; i < seg.size(); ++i) {
00061 const TrackSeg* trk = seg[i];
00062
00063 if (trk->NClust() < fMinNClust) continue;
00064
00065 int nGoodClu = 0;
00066
00067 memset(&ti, 0, sizeof(ti));
00068
00069 for (int c = kDC1; c < kNCham; ++c) {
00070 for (int p = 0; p < kNPlane; ++p) {
00071 const WireClust* wc = trk->Clust(c, p);
00072 if (!wc || wc->NWire() > 1) continue;
00073 nGoodClu++;
00074 ti.fWire[c - kDC1][p] = wc->AvgWire();
00075 ti.fWeight[c - kDC1][p] = 1.0 / (wc->USig() * wc->USig());
00076 }
00077 }
00078
00079 if (nGoodClu < fMinNClust) continue;
00080
00081
00082 Fit(ti, resid);
00083 for (int c = 0; c < 6 && nGoodClu > 0; ++c) {
00084 for (int p = 0; p < kNPlane; ++p) {
00085 if (ti.fWeight[c][p] > 1 &&
00086 fabs(resid[c][p]) > 1.5 * GChamGeo::Pitch(c + kDC1)) {
00087 nGoodClu = 0;
00088 break;
00089 }
00090 }
00091 }
00092
00093 if (nGoodClu < fMinNClust) continue;
00094
00095 fTrackList.push_back(ti);
00096 }
00097
00098 return kPassed;
00099 }
00100
00101
00102
00103 void AlignChamZNoBF::NewRun(int run, int )
00104 {
00105 GMIPPGeo::Instance(run);
00106 }
00107
00108
00109
00110 double AlignChamZNoBF::ComputeF()
00111 {
00112 if (fUseCorr) return ComputeCorrF();
00113 else return ComputeChi2F();
00114 }
00115
00116
00117
00118 double AlignChamZNoBF::ComputeChi2F()
00119 {
00120 double f = 0;
00121
00122 double u[24];
00123 double w[24];
00124 double z[24];
00125 double cosA[24];
00126 double sinA[24];
00127 double z1 = GMIPPGeo::Instance().Cham(kDC1).ZGas() - 50;
00128 double z2 = GMIPPGeo::Instance().Cham(kPWC6).ZGas() + 50;
00129 double par[4];
00130 double parErr[4];
00131
00132 for (unsigned int i = 0; i < fTrackList.size(); ++i) {
00133 TrkInfo_t& ti = fTrackList[i];
00134
00135 int nClu = 0;
00136
00137 for (int c = 0; c < 6; ++c) {
00138 GChamGeo& geo = GMIPPGeo::Instance().Cham(c + kDC1);
00139 for (int p = 0; p < kNPlane; ++p) {
00140 if (ti.fWeight[c][p] < 1e-3) continue;
00141
00142 geo.WireToU(p + 1, ti.fWire[c][p], u[nClu]);
00143 w[nClu] = ti.fWeight[c][p];
00144 z[nClu] = geo.Z(p + 1);
00145 cosA[nClu] = geo.GAngleCos(p + 1);
00146 sinA[nClu] = geo.GAngleSin(p + 1);
00147
00148 nClu++;
00149 }
00150 }
00151
00152 f += TrkRUtil::FitLineFromWires(nClu, u, w, z, cosA, sinA, z1, z2,
00153 par, parErr);
00154 }
00155 return f;
00156 }
00157
00158
00159
00160 double AlignChamZNoBF::ComputeCorrF() {
00161 double resid[6][kNPlane];
00162 int n[6][kNPlane];
00163 double x[6][kNPlane];
00164 double y[6][kNPlane];
00165 double xx[6][kNPlane];
00166 double yy[6][kNPlane];
00167 double xy[6][kNPlane];
00168 memset(x, 0, sizeof(x));
00169 memset(n, 0, sizeof(n));
00170 memset(y, 0, sizeof(y));
00171 memset(xx, 0, sizeof(xx));
00172 memset(yy, 0, sizeof(yy));
00173 memset(xy, 0, sizeof(xy));
00174
00175 for (unsigned int i = 0; i < fTrackList.size(); ++i) {
00176 TrkInfo_t& ti = fTrackList[i];
00177 double dxdz = Fit(ti, resid);
00178
00179 for (int c = 0; c < 6; ++c) {
00180 for (int p = 0; p < kNPlane; ++p) {
00181 if (ti.fWeight[c][p] < 1) continue;
00182 n[c][p]++;
00183 x[c][p] += dxdz;
00184 xx[c][p] += dxdz * dxdz;
00185 y[c][p] += resid[c][p];
00186 yy[c][p] += resid[c][p] * resid[c][p];
00187 xy[c][p] += dxdz * resid[c][p];
00188 }
00189 }
00190 }
00191 double f = 0;
00192 for (int c = 0; c < 6; ++c) {
00193 for (int p = 0; p < kNPlane; ++p) {
00194 if (n[c][p] < 10) continue;
00195
00196
00197 double corr = (n[c][p] * xy[c][p] - x[c][p] * y[c][p]);
00198 corr *= corr;
00199 corr /= (n[c][p] * xx[c][p] - x[c][p] * x[c][p]) *
00200 (n[c][p] * yy[c][p] - y[c][p] * y[c][p]);
00201 assert(fabs(corr) < 1);
00202
00203 f += corr;
00204 }
00205 }
00206 return f;
00207 }
00208
00209
00210
00211 double AlignChamZNoBF::Fit(TrkInfo_t& ti, double resid[6][4], float* dydz,
00212 float xc[6][4], float yc[6][4])
00213 {
00214 double u[24];
00215 double w[24];
00216 double z[24];
00217 double cosA[24];
00218 double sinA[24];
00219 double z1 = GMIPPGeo::Instance().Cham(kDC1).ZGas() - 50;
00220 double z2 = GMIPPGeo::Instance().Cham(kPWC6).ZGas() + 50;
00221 double par[4];
00222 double parErr[4];
00223 int plane[24];
00224
00225 int nClu = 0;
00226
00227 for (int c = 0; c < 6; ++c) {
00228 GChamGeo& geo = GMIPPGeo::Instance().Cham(c + kDC1);
00229 for (int p = 0; p < kNPlane; ++p) {
00230 if (ti.fWeight[c][p] < 1e-3) {
00231 resid[c][p] = 1e6;
00232 continue;
00233 }
00234
00235 geo.WireToU(p + 1, ti.fWire[c][p], u[nClu]);
00236 w[nClu] = ti.fWeight[c][p];
00237 z[nClu] = geo.Z(p + 1);
00238 cosA[nClu] = geo.GAngleCos(p + 1);
00239 sinA[nClu] = geo.GAngleSin(p + 1);
00240 plane[nClu] = c * 4 + p;
00241
00242 nClu++;
00243 }
00244 }
00245
00246 TrkRUtil::FitLineFromWires(nClu, u, w, z, cosA, sinA, z1, z2,
00247 par, parErr);
00248
00249 double x1[3] = {par[0], par[1], z1};
00250 double x2[3] = {par[2], par[3], z2};
00251 double x[3];
00252
00253 double dxdz = (par[2] - par[0]) / (z2 - z1);
00254 if (dydz) *dydz = (par[3] - par[1]) / (z2 - z1);
00255 if (xc && yc) {
00256 for (int c = 0; c < 6; ++c) {
00257 GChamGeo& geo = GMIPPGeo::Instance().Cham(c + kDC1);
00258 for (int p = 0; p < 4; ++p) {
00259 x[2] = geo.Z(p + 1);
00260 TrkRUtil::PredictXY(x1, 0, x2, 0, x, 0);
00261 xc[c][p] = x[0];
00262 yc[c][p] = x[1];
00263 }
00264 }
00265 }
00266
00267 for (int i = 0; i < nClu; ++i) {
00268 double saveW = w[i];
00269 w[i] = 0;
00270 TrkRUtil::FitLineFromWires(nClu, u, w, z, cosA, sinA, z1, z2,
00271 par, parErr);
00272 w[i] = saveW;
00273
00274 x1[0] = par[0];
00275 x1[1] = par[1];
00276 x2[0] = par[2];
00277 x2[1] = par[3];
00278 x[2] = z[i];
00279 TrkRUtil::PredictXY(x1, 0, x2, 0, x, 0);
00280
00281 int c = plane[i] / 4;
00282 int p = plane[i] % 4;
00283 GMIPPGeo::Instance().Cham(c + kDC1).XYToU(p + 1, x[0], x[1],
00284 resid[c][p]);
00285 resid[c][p] -= u[i];
00286 }
00287
00288 return dxdz;
00289 }
00290
00291
00292
00293 static void gsFCN(int& , double* , double& f,
00294 double* par, int )
00295 {
00296
00297 for (int i = 0; i < 6; ++i) {
00298 GMIPPGeo::Instance().Cham(i + kDC1).SetZGas(par[i]);
00299 GMIPPGeo::Instance().Cham(i + kDC1).SetGAngle(par[i + 6] * 1e-3);
00300 }
00301
00302 f = gModule->ComputeF();
00303 }
00304
00305
00306
00307 void AlignChamZNoBF::EndRun(int , int )
00308 {
00309 if (fTrackList.size() < 100) {
00310 cout << "Can't do alignment with " << fTrackList.size() << " tracks"
00311 << endl;
00312 return;
00313 }
00314
00315 cout << "Doing no B-field alignment with " << fTrackList.size()
00316 << " tracks" << endl;
00317
00318 MakeTree("pre");
00319
00320 gModule = this;
00321 TMinuit minu(12);
00322 minu.SetFCN(gsFCN);
00323
00324 char name[256];
00325 int ierr;
00326 double savePos[6], saveAng[6];
00327 for (int i = 0; i < 6; ++i) {
00328 GChamGeo& geo = GMIPPGeo::Instance().Cham(i + kDC1);
00329 sprintf(name, "%s_z", geo.Name());
00330 minu.mnparm(i, name, geo.ZGas(), 0.1,
00331 geo.ZGas() - 10, geo.ZGas() + 10, ierr);
00332 savePos[i] = geo.ZGas();
00333
00334 sprintf(name, "%s_angle", geo.Name());
00335 saveAng[i] = geo.GAngle(1) - geo.LAngle(1);
00336 minu.mnparm(i + 6, name, saveAng[i] * 1e3, 1, -5e2, 5e2, ierr);
00337 }
00338
00339 for (unsigned int i = 0; i < fFixCham.size(); ++i)
00340 minu.FixParameter(fFixCham[i]);
00341
00342 minu.Migrad();
00343
00344 MakeTree("post");
00345
00346 double par, pe;
00347 for (int i = 0; i < 6; ++i) {
00348 minu.GetParameter(i, par, pe);
00349 cout << GChamGeo::Name(i + kDC1) << " z shift: " << par - savePos[i]
00350 << " cm, err: " << pe << endl;
00351
00352 minu.GetParameter(i + 6, par, pe);
00353 cout << GChamGeo::Name(i + kDC1) << " angle shift: "
00354 << par * 1e-3 - saveAng[i] << " deg, err: " << pe << endl;
00355 }
00356 }
00357
00358
00359
00360 void AlignChamZNoBF::MakeTree(const char* name)
00361 {
00362 char str[256];
00363 sprintf(str, "%s-alignment Tree", name);
00364 TTree* tree = new TTree(name, str);
00365
00366 double u[6][4];
00367 float x[6][4];
00368 float y[6][4];
00369 double uperp[6][4];
00370 double resid[6][4];
00371 float dxdz;
00372 float dydz;
00373 tree->Branch("u", &u, "u[6][4]/D");
00374 tree->Branch("x", &x, "x[6][4]/D");
00375 tree->Branch("y", &y, "y[6][4]/D");
00376 tree->Branch("uperp", &uperp, "uperp[6][4]/D");
00377 tree->Branch("resid", &resid, "resid[6][4]/D");
00378 tree->Branch("dxdz", &dxdz, "dxdz/F");
00379 tree->Branch("dydz", &dydz, "dydz/F");
00380
00381 for (unsigned int i = 0; i < fTrackList.size(); ++i) {
00382 TrkInfo_t& ti = fTrackList[i];
00383
00384 dxdz = Fit(ti, resid, &dydz, x, y);
00385
00386 for (int c = 0; c < 6; ++c) {
00387 GChamGeo& geo = GMIPPGeo::Instance().Cham(c + kDC1);
00388 for (int p = 0; p < 4; ++p) {
00389 if (ti.fWeight[c][p] < 1e-3) u[c][p] = 1e6;
00390 else geo.WireToU(p + 1, ti.fWire[c][p], u[c][p]);
00391 geo.XYToUperp(p + 1, x[c][p], y[c][p], uperp[c][p]);
00392 }
00393 }
00394 tree->Fill();
00395 }
00396
00397 tree->Write();
00398 delete tree;
00399 }
00400
00401
00402
00403 void AlignChamZNoBF::Update(const CfgConfig& c)
00404 {
00405 fFixCham.clear();
00406 c("Debug").Get(fDebug);
00407 c("SegFolder").Get(fSegFolder);
00408 c("MinNClust").Get(fMinNClust);
00409 try { c("FixCham").Get(fFixCham); }
00410 catch (...) {
00411 int i;
00412 c("FixCham").Get(i);
00413 fFixCham.push_back(i);
00414 }
00415 c("UseCorr").Get(fUseCorr);
00416
00417
00418 fIsInit = true;
00419 }
00420
00421