00001
00002
00003
00004
00005
00006
00007 #include "TrackFit/Circe.h"
00008 #include <iostream>
00009 #include <cmath>
00010 #include "Minuit2/Minuit2Minimizer.h"
00011 #include "Geometry/geo.h"
00012 #include "RecoBase/CellHit.h"
00013 #include "RecoBase/Prong.h"
00014 using namespace trk;
00015
00017 unsigned int Circe::NDim() const { return 2*fN+3; }
00018
00030 double Circe::DoEval(const double* par) const
00031 {
00032 unsigned register int i;
00033 unsigned register int j;
00034
00035
00036 if (fN>kNmax) {
00037 std::cerr << __FILE__ << ":" << __LINE__
00038 << " Can't fit more than " << kNmax << " prongs."
00039 << std::endl;
00040 abort();
00041 }
00042
00043
00044
00045 double vtx[3];
00046 double endpoint[kNmax][3];
00047 double theta;
00048 double phi;
00049 double ds = 10.0E2;
00050 std::vector<unsigned int> prongassn(fM->fHits.size());
00051
00052
00053 vtx[0] = par[2*fN+0];
00054 vtx[1] = par[2*fN+1];
00055 vtx[2] = par[2*fN+2];
00056
00057
00058 for (i=0; i<fN; ++i) {
00059 theta = par[2*i+0];
00060 phi = par[2*i+1];
00061 endpoint[i][0] = vtx[0]+ds*sin(theta)*cos(phi);
00062 endpoint[i][1] = vtx[1]+ds*sin(theta)*sin(phi);
00063 endpoint[i][2] = vtx[2]+ds*cos(theta);
00064 }
00065
00066 double x0;
00067 double x1;
00068 double x2;
00069 double y0;
00070 double y1;
00071 double y2;
00072 double dsqr;
00073 double dsqrmin;
00074 double dot;
00075 double score = 0.0;
00076
00077
00078 for (j=0; j<fM->fHits.size(); ++j) {
00079 const recobase::CellHit& h = (*fM->fHits[j]);
00080
00081 x0 = h.ZCPos();
00082 y0 = h.TCPos();
00083
00084 dsqrmin = 99.E99;
00085 for (i=0; i<fN; ++i) {
00086 if (h.View()==geo::kX) {
00087 x1 = vtx[2];
00088 y1 = vtx[0];
00089 x2 = endpoint[i][2];
00090 y2 = endpoint[i][0];
00091 }
00092 else if (h.View()==geo::kY) {
00093 x1 = vtx[2];
00094 y1 = vtx[1];
00095 x2 = endpoint[i][2];
00096 y2 = endpoint[i][1];
00097 }
00098 else abort();
00099
00100
00101 dot = (x0-x1)*(x2-x1) + (y0-y1)*(y2-y1);
00102 if (dot>=0.0) {
00103 dsqr = geo::DsqrToLine(x0, y0, x1, y1, x2, y2);
00104 }
00105 else {
00106 dsqr = pow(x0-x1,2)+pow(y0-y1,2);
00107 }
00108 if (dsqr<dsqrmin) dsqrmin = dsqr;
00109 }
00110 score += fM->fW[j]*dsqrmin;
00111 }
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 return score;
00126 }
00127
00128
00133 ROOT::Math::IMultiGenFunction* Circe::Clone() const { return 0; }
00134
00135
00143 void Circe::SeedProngs(const Measurement* meas,
00144 unsigned int nprong,
00145 double* seed) const
00146 {
00147
00148
00149 double sumx=0.0;
00150 double sumy=0.0;
00151 double sumz=0.0;
00152 double sumwx=0.0;
00153 double sumwy=0.0;
00154 double sumwz=0.0;
00155 for (unsigned int i=0; i<meas->fHits.size(); ++i) {
00156 const recobase::CellHit& h = (*meas->fHits[i]);
00157 if (h.View()==geo::kX) {
00158 sumx += meas->fW[i]*h.TCPos();
00159 sumwx += meas->fW[i];
00160 }
00161 if (h.View()==geo::kY) {
00162 sumy += meas->fW[i]*h.TCPos();
00163 sumwy += meas->fW[i];
00164 }
00165 sumz += meas->fW[i]*h.ZCPos();
00166 sumwz += meas->fW[i];
00167 }
00168 seed[2*fN+0] = sumx/sumwx;
00169 seed[2*fN+1] = sumy/sumwy;
00170 seed[2*fN+2] = sumz/sumwz;
00171
00172
00173
00174 for (unsigned int i=0; i<nprong; ++i) {
00175 if (i==0) {
00176 seed[2*i+0] = 0.0;
00177 seed[2*i+1] = 0.0;
00178 }
00179 else {
00180 seed[2*i+0] = 0.0;
00181 seed[2*i+1] = M_PI*(float)i/(float)(nprong-1);
00182 }
00183 }
00184 }
00185
00186
00195 double Circe::Fit(int nprong, const Measurement* meas)
00196 {
00197 double seed[2*kNmax+3];
00198
00199
00200 fN = nprong;
00201 fM = meas;
00202
00203
00204 this->SeedProngs(meas, nprong, seed);
00205
00206
00207
00208 ROOT::Minuit2::Minuit2Minimizer mini;
00209 mini.SetPrintLevel(0);
00210 mini.SetTolerance(0.1);
00211 mini.SetStrategy(2);
00212 mini.SetMaxFunctionCalls(10000);
00213
00214 for (unsigned int i=0; i<fN; ++i) {
00215 char buff1[16];
00216 char buff2[16];
00217 sprintf(buff1, "theta_%d",i);
00218 sprintf(buff2, "phi_%d", i);
00219 mini.SetVariable(2*i+0, buff1, seed[2*i+0], 0.1);
00220 mini.SetVariable(2*i+1, buff2, seed[2*i+1], 0.1);
00221 }
00222 mini.SetVariable(2*fN+0, "x0", seed[2*fN+0], 10.0);
00223 mini.SetVariable(2*fN+1, "y0", seed[2*fN+1], 10.0);
00224 mini.SetVariable(2*fN+2, "z0", seed[2*fN+2], 10.0);
00225
00226 mini.SetFunction(*this);
00227 mini.Minimize();
00228
00229
00230 for (unsigned int i=0; i<fN; ++i) {
00231 char buff1[16];
00232 char buff2[16];
00233 sprintf(buff1, "theta_%d",i);
00234 sprintf(buff2, "phi_%d", i);
00235 mini.SetVariable(2*i+0, buff1, mini.X()[2*i+0], 0.1);
00236 mini.SetVariable(2*i+1, buff2, mini.X()[2*i+1], 0.1);
00237 }
00238 mini.SetVariable(2*fN+0, "x0", mini.X()[2*fN+0], 10.0);
00239 mini.SetVariable(2*fN+1, "y0", mini.X()[2*fN+1], 10.0);
00240 mini.SetVariable(2*fN+2, "z0", mini.X()[2*fN+2], 10.0);
00241 mini.Minimize();
00242
00243
00244 for (unsigned int i=0; i<fN; ++i) {
00245 fTheta[i] = mini.X()[2*i+0];
00246 fPhi[i] = mini.X()[2*i+1];
00247 }
00248 fVtx[0] = mini.X()[2*fN+0];
00249 fVtx[1] = mini.X()[2*fN+1];
00250 fVtx[2] = mini.X()[2*fN+2];
00251
00252
00253
00254 double ndof = (float)((2*meas->fHits.size())-(2*fN+3));
00255 if (ndof<1.0) ndof = 1.0;
00256 return sqrt(mini.MinValue()/ndof);
00257 }
00258
00259
00260
00261 void Circe::MakeProngs(std::vector<recobase::Prong>& prong)
00262 {
00263 for (unsigned int i=0; i<fN; ++i) {
00264 recobase::Prong p;
00265
00266 p.SetStart(fVtx);
00267
00268 double ds = 1.E2;
00269 double xend[3];
00270 xend[0] = fVtx[0] + ds*sin(fTheta[i])*cos(fPhi[i]);
00271 xend[1] = fVtx[1] + ds*sin(fTheta[i])*sin(fPhi[i]);
00272 xend[2] = fVtx[2] + ds*cos(fTheta[i]);
00273 p.SetStop(xend);
00274
00275 prong.push_back(p);
00276 }
00277 }
00278