Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Circe.cxx

Go to the documentation of this file.
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   // Assert that limit on the number of prongs is observed
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   // Unpack the input data. For convenience "track" the particles by
00044   // projecting them from the vertex 10 meters
00045   double vtx[3];
00046   double endpoint[kNmax][3];
00047   double theta;
00048   double phi;
00049   double ds = 10.0E2; // path length in cm
00050   std::vector<unsigned int> prongassn(fM->fHits.size());
00051 
00052   // Vertex location is last on the list
00053   vtx[0] = par[2*fN+0];
00054   vtx[1] = par[2*fN+1]; 
00055   vtx[2] = par[2*fN+2];
00056 
00057   // Direction angles are the first 2n variables
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;          // Transverse hit        location (cm)
00067   double x1;          // Transverse vertex     location (cm)
00068   double x2;          // Transverse endpoint   location (cm)
00069   double y0;          // Longitudinal hit      location (cm)
00070   double y1;          // Longitudinal vertex   location (cm)
00071   double y2;          // Longitudinal endpoint location (cm)
00072   double dsqr;        // Distance^2 from prong to hit
00073   double dsqrmin;     // Shortest distance to any prong
00074   double dot;
00075   double score = 0.0; // Chi^2 score of comparison
00076   
00077   // Loop on all hits and find the prong they are closest to
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       // Check if the point is in the forward dirction. If not use the
00100       // distance to the vertex location as the score
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   std::cout << "chi^2=" << score << "\n";
00114   std::cout << "vtx=("
00115             << par[2*fN+0] << " " 
00116             << par[2*fN+1] 
00117             << par[2*fN+2] 
00118             << ")" << std::endl;
00119   for (unsigned int i=0; i<fN; ++i) {
00120     std::cout << "( " 
00121               << par[2*i+0] << ","
00122               << par[2*i+1] << ")" << std::endl;
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   // Choose vertex position at most upstream end in z
00148   // direction. That's where the neutrinos come from...
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   // See the directions so that the first goes along the beam
00173   // direction and the others are distributed around in the x-y plane
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   // Setup the fitter
00200   fN = nprong;
00201   fM = meas;
00202 
00203   // Seed the fit
00204   this->SeedProngs(meas, nprong, seed);
00205 
00206   // Setup one of the root minimizers
00207   // ROOT::Minuit2::Minuit2Minimizer mini(ROOT::Minuit2::kSimplex);
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   // Re-do the fit to guard against local minima
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   // Unpack the results of the fit
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   // Return the standard deviation as a measure of goodness and
00253   // doneness
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; // track length in meters
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 

Generated on Mon Nov 23 04:45:25 2009 for NOvA Offline by  doxygen 1.3.9.1