00001 #include<TMuiRoadFinder.h>
00002 #include<TMuiChannelId.hh>
00003 #include<PHGeometry.h>
00004 #include<gsl/gsl_fit.h>
00005 #include<boost/array.hpp>
00006 #include<cmath>
00007 #include<TROOT.h>
00008 #include<TMuiClusterMapO.h>
00009 #include<TMuiHitMapO.h>
00010 #include<TMuiMCHitMapO.h>
00011 
00012 
00013 
00014 bool TMuiRoadFinder::_verbose = false;
00015 bool TMuiRoadFinder::_reverse_algo = false;
00016 
00017 UShort_t TMuiRoadFinder::_min_cluster = 4;
00018 UShort_t TMuiRoadFinder::_min_point = 2;
00019 
00020 UShort_t TMuiRoadFinder::_max_cluster_share = 4;
00021 
00022 bool TMuiRoadFinder::_evaluation = false; 
00023 TNtuple* TMuiRoadFinder::_ntuple = 0; 
00024 TFile* TMuiRoadFinder::_file = 0; 
00025     
00026 
00027 
00028 bool TMuiRoadFinder::Road::_verbose = false;
00029 
00030 double TMuiRoadFinder::Road::_dca_cut = 4.0;  
00031 double TMuiRoadFinder::Road::_prox_cut = 4.0;
00032 
00033 
00034 double TMuiRoadFinder::Road::_orient_z_dist = 2.0;
00035 double TMuiRoadFinder::Road::_tube_width = 8.35; 
00036 
00037 bool TMuiRoadFinder::Road::_evaluation = false; 
00038 bool TMuiRoadFinder::Road::_use_slope_cuts = false; 
00039 TFile* TMuiRoadFinder::Road::_file = 0; 
00040 TNtuple* TMuiRoadFinder::Road::_ntuple = 0; 
00041 boost::array<float,20> TMuiRoadFinder::Road::_eval_data;
00042 
00043 
00044 
00045 
00046 
00047 void
00048 TMuiRoadFinder::find(TMuiClusterMapO* cluster_map)
00049 {
00050   
00051   
00052   if(!cluster_map) throw std::logic_error(DESCRIPTION("TMuiClusterMapO pointer is null"));
00053 
00054   for(int arm=0; arm<MUIOO::NumberOfArms;++arm){
00055     find(cluster_map, arm);
00056   }  
00057 }
00058 
00059 
00060 
00061 void
00062 TMuiRoadFinder::find(TMuiClusterMapO* cluster_map,
00063                      UShort_t arm,
00064                      bool use_window,
00065                      const road_window& theta_window,
00066                      const road_window& phi_window) 
00067 {
00068   if(_verbose) {
00069     std::cout << " TMuiRoadFinder::find: location: " << " arm: " << arm << std::endl;
00070   }
00071   
00072   
00073   if(!cluster_map) throw std::logic_error(DESCRIPTION("TMuiClusterMapO pointer is null"));  
00074 
00075   
00076   
00077   typedef std::list<TMuiClusterMapO::value_type> local_list_type;
00078   local_list_type local_list;
00079 
00080   
00081   
00082   TMuiClusterMapO::iterator cluster_iter = cluster_map->get(arm);
00083   while(TMuiClusterMapO::pointer cluster_ptr = cluster_iter.next()){
00084     local_list.push_back(*cluster_ptr);
00085   }
00086 
00087   
00088   
00089   local_list_type::iterator iter = local_list.begin();
00090   for(;iter!=local_list.end();++iter){
00091     
00092     
00093     bool was_appended = append_to_road(&(*iter));
00094     if(!was_appended){
00095       start_new_road(&(*iter), use_window, theta_window, phi_window);
00096     } 
00097     if(_verbose) print_roads();
00098   }
00099 
00100   
00101   
00102   
00103   set_complete_tag();
00104 
00105   
00106   
00107   remove_includes();
00108 
00109   
00110   
00111   if(!_reverse_algo) return;
00112   
00113   
00114   
00115   local_list.reverse();
00116 
00117   
00118   
00119   iter = local_list.begin();
00120   for(;iter!=local_list.end();++iter){
00121     
00122     
00123     bool was_appended = append_to_road(&(*iter));
00124     if(!was_appended){
00125       start_new_road(&(*iter), use_window, theta_window, phi_window);
00126     }
00127     if(_verbose) print_roads();
00128   }
00129   
00130   
00131   
00132   set_complete_tag();    
00133   
00134   size_t n_road = _road_list.size();
00135   _road_list.sort(road_less_ftor());
00136   _road_list.unique(road_equal_ftor());
00137   
00138   
00139   
00140   remove_includes();
00141   
00142   if(_verbose) {
00143     std::cout << " removed " << n_road - _road_list.size() << " duplicate roads" << std::endl;
00144   }
00145 }
00146 
00147 void 
00148 TMuiRoadFinder::remove_includes()
00149 {
00150   road_list::iterator iter1 = _road_list.begin();
00151   for(;iter1!=_road_list.end();++iter1){
00152     if (!iter1->get_status()) continue; 
00153     road_list::iterator iter2 = iter1;
00154     ++iter2;
00155     for(;iter2!=_road_list.end();++iter2){
00156       if (!iter2->get_status()) continue; 
00157 
00158       road_list::iterator big = (iter1->get_n_cluster() >= iter2->get_n_cluster()) ? iter1 : iter2;
00159       road_list::iterator little = (iter1->get_n_cluster() >= iter2->get_n_cluster()) ? iter2 : iter1;
00160 
00161       
00162       
00163       if(std::includes(big->get_cluster_list().begin(),
00164                        big->get_cluster_list().end(),
00165                        little->get_cluster_list().begin(),
00166                        little->get_cluster_list().end())) {
00167         little->set_status(false);
00168       }      
00169 
00170       
00171       
00172       
00173       UShort_t nshare = 0;
00174 
00175       Road::cluster_list::const_iterator big_iter = 
00176         big->get_cluster_list().begin();
00177       Road::cluster_list::const_iterator little_iter = 
00178         little->get_cluster_list().begin();
00179       for(;big_iter!=big->get_cluster_list().end();++big_iter){
00180         bool match = false;
00181         little_iter = little->get_cluster_list().begin();
00182         for(;little_iter!=little->get_cluster_list().end();++little_iter){
00183           if(big_iter->get()->get_key().get_obj_key()  
00184              == little_iter->get()->get_key().get_obj_key()) {
00185             match = true;
00186           }
00187         }
00188         if (match) nshare++;
00189       }
00190       if (nshare > _max_cluster_share) {    
00191         little->set_status(false);
00192       }
00193     }
00194   }  
00195   
00196   
00197   _road_list.remove_if(road_bad_status_ftor());    
00198 }
00199 
00200 void
00201 TMuiRoadFinder::set_complete_tag()
00202 {
00203   road_list::iterator road_iter = _road_list.begin();
00204   road_iter = _road_list.begin();
00205   for(;road_iter!=_road_list.end();++road_iter) {
00206     if(road_iter->get_cluster_list().size() < _min_cluster ||
00207        road_iter->get_point_list().size() < _min_point) {
00208       road_iter->set_status(false);
00209     } else {
00210       road_iter->set_complete(true);
00211     }
00212   }
00213   _road_list.remove_if(road_bad_status_ftor());    
00214 }
00215 
00216 bool 
00217 TMuiRoadFinder::append_to_road(TMuiClusterMapO::pointer cluster_ptr)
00218 {    
00219   
00220   
00221   
00222   
00223   
00224   
00225   
00226   
00227   bool sticky_appended = false;
00228   road_list::iterator road_iter = _road_list.begin();
00229   for(;road_iter!=_road_list.end();++road_iter){
00230     
00231     
00232     
00233     if(road_iter->is_complete()) continue;
00234     
00235     
00236     
00237     bool was_appended =  road_iter->add_cluster(cluster_ptr);
00238     sticky_appended = (sticky_appended) ? sticky_appended : was_appended;    
00239   }
00240   return sticky_appended;
00241 }
00242 
00243 void
00244 TMuiRoadFinder::print_roads() const
00245 {
00246   MUIOO::PRINT(std::cout,"**");
00247   std::for_each(_road_list.begin(), _road_list.end(), road_print_ftor());
00248   MUIOO::PRINT(std::cout,"**");
00249 }
00250 
00251 void
00252 TMuiRoadFinder::abort_new_road()
00253 {
00254   _road_list.pop_front();                           
00255 }
00256 
00257 TMuiRoadFinder::Road*
00258 TMuiRoadFinder::start_new_road(TMuiClusterMapO::pointer cluster_ptr,
00259                                bool use_window,
00260                                const road_window& theta_window,
00261                                const road_window& phi_window)
00262 {
00263   _road_list.push_front(Road(this, cluster_ptr, use_window,
00264                              theta_window, phi_window));                            
00265 
00266   
00267   
00268   return &(*_road_list.begin());
00269 }
00270 
00271 
00272 
00273 
00274 bool 
00275 TMuiRoadFinder::Road::add_cluster(TMuiClusterMapO::pointer cluster_ptr) 
00276 {
00277   bool was_added=false;
00278   if(_evaluation) _eval_data.assign(0);
00279 
00280   
00281   
00282   
00283   if(!unique_check(cluster_ptr)) {
00284     if(_clusters.size()>1) {
00285       was_added = bifurcate(cluster_ptr);
00286       return was_added;
00287     } else {
00288       return false; 
00289     }
00290   } 
00291   
00292   
00293   
00294 
00295   
00296   
00297   
00298   
00299   
00300   
00301   
00302   
00303   
00304   
00305   
00306   
00307   
00308   
00309   if(_points.size() != 0){
00310 
00311     PHPoint point = project(cluster_ptr->get()->get_centroidpos().getZ());
00312     if(test_window(point) && 
00313        check_dca(cluster_ptr,point) &&
00314        check_proximity(cluster_ptr)){
00315       update_road(cluster_ptr);
00316       was_added = true;
00317     }
00318     
00319   } 
00320   else {
00321     
00322     
00323     if(!check_parallel(cluster_ptr)) {
00324       
00325       
00326       if (has_window()) {
00327         PHPoint point = make_point(cluster_ptr);
00328         
00329         
00330         if(test_window(point)){
00331           update_road(cluster_ptr);
00332           was_added = true;
00333         }
00334       }
00335       else {
00336         update_road(cluster_ptr);
00337         was_added = true;
00338       } 
00339     }
00340     else {
00341       
00342       
00343       
00344       if (check_proximity(cluster_ptr)) {
00345         update_road(cluster_ptr);
00346         was_added = true;
00347       }
00348     }
00349   }  
00350 
00351   if(_clusters.size() >= 3){
00352     check_slope();
00353   }
00354   if(_evaluation) {
00355     _eval_data[0] = _arm;
00356     _eval_data[1] = cluster_ptr->get()->get_plane();
00357     _eval_data[2] = cluster_ptr->get()->get_panel();
00358     _eval_data[3] = cluster_ptr->get()->get_orientation();
00359     _eval_data[4] = _clusters.size(); 
00360     _eval_data[5] = was_added ? 1 : 0; 
00361     _ntuple->Fill(&(_eval_data[0]));
00362   }
00363   return was_added;
00364 }
00365  
00366 bool 
00367 TMuiRoadFinder::Road::check_parallel(const TMuiClusterMapO::pointer cluster_ptr) const 
00368 {  
00369   
00370   
00371   cluster_list::const_iterator cluster_iter = _clusters.begin();
00372   for(;cluster_iter!=_clusters.end();++cluster_iter){
00373     if ( (cluster_iter->get()->get_plane() == cluster_ptr->get()->get_plane()) && 
00374          (cluster_iter->get()->get_panel() == cluster_ptr->get()->get_panel()) && 
00375          (cluster_iter->get()->get_orientation() != cluster_ptr->get()->get_orientation()) ) {
00376       return false;
00377     }
00378   }
00379   return true;
00380 }
00381 
00382 bool
00383 TMuiRoadFinder::Road::check_slope() const
00384 {
00385   return true;
00386 }
00387 
00388 bool 
00389 TMuiRoadFinder::Road::test_window(const PHPoint& point) const
00390 {
00391   
00392   
00393   
00394   if (!has_window()) {
00395     return true;
00396   }
00397   
00398   
00399   
00400   
00401   if (_points.size() == 0) {
00402     return true;
00403   }
00404 
00405   TMuiRoadFinder::WindowEnum phi_check = 
00406     TMuiRoadFinder::check_phi_window(point,_phi_window);
00407 
00408   TMuiRoadFinder::WindowEnum theta_check = 
00409     TMuiRoadFinder::check_theta_window(point,_theta_window);
00410 
00411   if(_evaluation) {
00412     _eval_data[6] = phi_check; 
00413     _eval_data[7] = theta_check; 
00414     _eval_data[10] = point.getX(); 
00415     _eval_data[11] = point.getY();
00416     _eval_data[12] = point.getZ();  
00417     _eval_data[13] = _phi_window.first;  
00418     _eval_data[14] = _phi_window.second;  
00419     _eval_data[15] = _theta_window.first;  
00420     _eval_data[16] = _theta_window.second;  
00421   }
00422 
00423   if(phi_check == TMuiRoadFinder::IN_WINDOW && 
00424      theta_check == TMuiRoadFinder::IN_WINDOW) {
00425     return true;
00426   } 
00427   else {
00428     return false;
00429   }
00430 }
00431 
00432 bool 
00433 TMuiRoadFinder::Road::check_dca(const TMuiClusterMapO::pointer cluster_ptr, 
00434                                 const PHPoint& point)  const 
00435 {
00436   
00437   PHLine line = cluster_ptr->get()->get_coord();
00438   double distance = PHGeometry::distanceLinePoint(line, point);
00439   
00440   
00441   if (_tube_width > 0) distance /= _tube_width; 
00442   else return false;
00443        
00444   if(_evaluation) {
00445     _eval_data[8] = distance; 
00446   }
00447  
00448   if(distance < _dca_cut) {
00449     
00450     
00451     
00452     
00453     double projdist = PHGeometry::distancePointToPoint(cluster_ptr->get()->get_centroidpos(), point);
00454     double halflength = 0.5*line.length();
00455     if (projdist < halflength) {
00456       return true;
00457     }
00458   }
00459   return false;
00460 }
00461 
00462 bool
00463 TMuiRoadFinder::Road::bifurcate(TMuiClusterMapO::pointer cluster_ptr)  
00464 {
00465   
00466   
00467   if(_finder->_road_list.size() > 500) {
00468     throw std::runtime_error(DESCRIPTION("bifurcate: too many roads"));
00469   }
00470 
00471   
00472   
00473   TMuiRoadFinder::Road* new_road_ptr = 0;
00474   
00475   
00476   
00477   
00478   cluster_list::iterator cluster_iter = _clusters.begin();
00479   for(;cluster_iter!=_clusters.end();++cluster_iter){
00480     if(cluster_ptr->get()->get_plane() != cluster_iter->get()->get_plane()) {      
00481       
00482       
00483       TMuiClusterMapO::value_type old_cluster = *cluster_iter;
00484 
00485       
00486       
00487       if(!new_road_ptr) {
00488         new_road_ptr = _finder->start_new_road(&old_cluster, _has_window, _theta_window, _phi_window);
00489       } else {
00490         new_road_ptr->update_road(&old_cluster);
00491       }
00492     }
00493   }
00494 
00495   
00496   
00497   if(!new_road_ptr) {
00498     _finder->start_new_road(cluster_ptr, _has_window, _theta_window, _phi_window);
00499     return true;
00500   }
00501   
00502   
00503   
00504   
00505   
00506   
00507   
00508   bool was_added = new_road_ptr->add_cluster(cluster_ptr);
00509   if(was_added) {
00510     return true;
00511   } else {
00512     _finder->abort_new_road();
00513     return false;
00514   }
00515 }
00516 
00517 
00518 bool 
00519 TMuiRoadFinder::Road::check_proximity(TMuiClusterMapO::pointer cluster_ptr) const 
00520 {
00521   
00522   
00523   
00524   
00525   
00526   
00527   if(!_clusters.size()) throw std::logic_error(DESCRIPTION("attempted comparison with null entry"));
00528 
00529   PHPoint point1 = cluster_ptr->get()->get_centroidpos();
00530 
00531   
00532   double distance = DBL_MAX;
00533   cluster_list::const_iterator best_iter;
00534   cluster_list::const_iterator cluster_iter = _clusters.begin();
00535   for(;cluster_iter!=_clusters.end();++cluster_iter){
00536     if (cluster_iter->get()->get_orientation() == cluster_ptr->get()->get_orientation()) {
00537       PHPoint point2 = cluster_iter->get()->get_centroidpos();
00538       double thisdistance = std::fabs(point2.getZ() - point1.getZ());
00539       if (thisdistance < distance) {
00540         distance = thisdistance;
00541         best_iter = cluster_iter;
00542       }
00543     }
00544   }
00545 
00546   if (distance == DBL_MAX) { 
00547     
00548     return false;
00549   }
00550 
00551   PHPoint point2 = best_iter->get()->get_centroidpos();
00552   point1.setZ(0);
00553   point2.setZ(0);
00554   distance = PHGeometry::distancePointToPoint(point1,point2);
00555 
00556   if (_tube_width > 0) distance /= _tube_width; 
00557   else return false;
00558 
00559   if(_evaluation) {
00560     _eval_data[9] = distance; 
00561   }
00562 
00563   if(distance < _prox_cut) {
00564     return true;
00565   }
00566   return false;
00567 }
00568 
00569 void
00570 TMuiRoadFinder::Road::update_road(TMuiClusterMapO::pointer cluster_ptr) 
00571 {
00572   
00573   
00574   _clusters.insert(*cluster_ptr);
00575   
00576   
00577   
00578   
00579   _points.clear();
00580 
00581   
00582   
00583   
00584   cluster_list::const_iterator iter1 = _clusters.begin();
00585   for(;iter1!=_clusters.end();++iter1){
00586 
00587     PHLine line1 = iter1->get()->get_coord();
00588     cluster_list::const_iterator iter2 = iter1;
00589     ++iter2;
00590     
00591     for(;iter2!=_clusters.end();++iter2){
00592      
00593       if(iter1->get()->get_plane() == iter2->get()->get_plane() &&
00594          iter1->get()->get_panel() == iter2->get()->get_panel() &&
00595          iter1->get()->get_orientation() != iter2->get()->get_orientation() ){
00596 
00597         PHLine line2 = iter2->get()->get_coord();
00598 
00599         
00600         double distance = PHGeometry::distanceLineLine(line1, line2);
00601         
00602         if (distance <= _orient_z_dist) 
00603           {
00604             PHPoint point = PHGeometry::closestApproachLineLine(line1, line2);
00605             _points.push_back(point);
00606           }
00607       }
00608     }
00609   }
00610 
00611   
00612   
00613   if(_points.size()==0){
00614 
00615     
00616     
00617     
00618     iter1 = _clusters.begin();
00619     PHPoint mid_point = iter1->get()->get_centroidpos();
00620     
00621     
00622     _fit_par.set_x(mid_point.getX());
00623     _fit_par.set_y(mid_point.getY());
00624     _fit_par.set_z(mid_point.getZ());
00625     _fit_par.set_dxdz(0);
00626     _fit_par.set_dydz(0);    
00627   } 
00628   else if(_points.size()==1){
00629     
00630     
00631     
00632     _fit_par.set_x(_points.begin()->getX());
00633     _fit_par.set_y(_points.begin()->getY());
00634     _fit_par.set_z(_points.begin()->getZ());
00635     _fit_par.set_dxdz(0);
00636     _fit_par.set_dydz(0);
00637 
00638     
00639     PHSphPoint spherepoint;
00640     PHGeometry::cartesianToSpherical(_points[0], spherepoint);
00641     double half_phi_window_size = 0.5*(_phi_window.second - _phi_window.first);
00642     double half_theta_window_size = 0.5*(_theta_window.second - _theta_window.first);
00643 
00644     _phi_window.first = static_cast<double>(spherepoint.getPhi())
00645       - half_phi_window_size; 
00646     _phi_window.second = static_cast<double>(spherepoint.getPhi())
00647       + half_phi_window_size; 
00648     _theta_window.first = static_cast<double>(spherepoint.getTheta())
00649       - half_theta_window_size;  
00650     _theta_window.second = static_cast<double>(spherepoint.getTheta())
00651       + half_theta_window_size; 
00652   } 
00653   else if(_points.size()>1) {
00654 
00655     
00656     
00657     
00658     boost::array<double,MUIOO::MAX_PLANE> x = {{0}}; 
00659     boost::array<double,MUIOO::MAX_PLANE> y = {{0}}; 
00660     boost::array<double,MUIOO::MAX_PLANE> z = {{0}}; 
00661       
00662     double z0 = _points[0].getZ();
00663     size_t n_data = _points.size();
00664 
00665     
00666     double z_max = -DBL_MAX; 
00667     double z_min = DBL_MAX;
00668 
00669     PHSphPoint spherepoint;
00670     double phi_sum = 0.0;
00671     double theta_sum = 0.0;
00672     double half_phi_window_size = 0.5*(_phi_window.second - _phi_window.first);
00673     double half_theta_window_size = 0.5*(_theta_window.second - _theta_window.first);
00674 
00675     for(size_t i=0;i<n_data;++i){
00676       PHGeometry::cartesianToSpherical(_points[i], spherepoint);
00677       phi_sum += spherepoint.getPhi();
00678       theta_sum += spherepoint.getTheta();
00679       x.at(i) = _points[i].getX();
00680       y.at(i) = _points[i].getY();
00681       z.at(i) = _points[i].getZ() - z0;
00682       z_min = std::min(z_min,_points[i].getZ());
00683       z_max = std::max(z_max,_points[i].getZ());
00684     }
00685 
00686     phi_sum /= n_data;
00687     theta_sum /= n_data;
00688     _phi_window.first = phi_sum - half_phi_window_size; 
00689     _phi_window.second = phi_sum + half_phi_window_size; 
00690     _theta_window.first = theta_sum - half_theta_window_size;  
00691     _theta_window.second = theta_sum + half_theta_window_size;  
00692 
00693     double x0=0,m_x=0, y0=0, m_y=0;
00694     double cov00=0, cov11=0, cov22=0,chi2x=0,chi2y=0;
00695       
00696     
00697     
00698     gsl_fit_linear(z.begin(),1,x.begin(),1,n_data,
00699                    &x0,&m_x,&cov00,&cov11,&cov22,&chi2x);
00700       
00701     
00702     
00703     gsl_fit_linear(z.begin(),1,y.begin(),1,n_data,
00704                    &y0,&m_y,&cov00,&cov11,&cov22,&chi2y);
00705 
00706     
00707     
00708     if(std::fabs(m_x) > 10 || std::fabs(m_y) > 10) {
00709       _status = false;
00710       return;
00711     }
00712 
00713     _fit_par.set_x(x0);
00714     _fit_par.set_y(y0);
00715     _fit_par.set_z(z0);
00716     _fit_par.set_dxdz(m_x);
00717     _fit_par.set_dydz(m_y);
00718     
00719     
00720     
00721     if(_arm == MUIOO::South) {
00722       _fit_par.set_z_begin(z_max) ;
00723       _fit_par.set_z_end(z_min);
00724     } else {
00725       _fit_par.set_z_begin(z_min) ;
00726       _fit_par.set_z_end(z_max);
00727     }
00728   }
00729 }
00730 
00731 PHPoint
00732 TMuiRoadFinder::Road::project(double z) const 
00733 {
00734   return TMutTrackUtil::linear_track_model(&_fit_par,z);
00735 }
00736 
00737 PHPoint
00738 TMuiRoadFinder::Road::make_point(const TMuiClusterMapO::pointer cluster_ptr) const 
00739 {  
00740   
00741   PHLine line1 = cluster_ptr->get()->get_coord();
00742   
00743   
00744   cluster_list::const_iterator cluster_iter = _clusters.begin();
00745   for(;cluster_iter!=_clusters.end();++cluster_iter){
00746     if ( (cluster_iter->get()->get_plane() == cluster_ptr->get()->get_plane()) && 
00747          (cluster_iter->get()->get_panel() == cluster_ptr->get()->get_panel()) && 
00748          (cluster_iter->get()->get_orientation() != cluster_ptr->get()->get_orientation()) ) { 
00749       
00750       PHLine line2 = cluster_iter->get()->get_coord();
00751       
00752       double distance = PHGeometry::distanceLineLine(line1, line2);
00753         
00754       if (distance <= _orient_z_dist) 
00755         {
00756           PHPoint point = PHGeometry::closestApproachLineLine(line1, line2);
00757           return point;
00758         }
00759     }
00760   }
00761   return PHPoint();
00762 }
00763 
00764 bool
00765 TMuiRoadFinder::Road::unique_check(TMuiClusterMapO::pointer cluster_ptr) const
00766 {
00767   
00768   
00769   
00770   cluster_list::const_iterator cluster_iter = _clusters.begin();
00771   for(;cluster_iter!=_clusters.end();++cluster_iter){
00772     
00773    if(cluster_ptr->get()->get_plane() == cluster_iter->get()->get_plane() &&
00774       cluster_ptr->get()->get_orientation() == cluster_iter->get()->get_orientation()) {
00775      return false;
00776    }
00777   }
00778   return true;
00779 }
00780 
00781 bool
00782 TMuiRoadFinder::Road::check_theta_window(const TMuiRoadFinder::road_window& theta_window) const 
00783 {
00784   double theta = get_theta();
00785   return (theta > theta_window.first && theta < theta_window.second);
00786 }
00787 
00788 bool
00789 TMuiRoadFinder::Road::check_phi_window(const TMuiRoadFinder::road_window& phi_window) const 
00790 {
00791   
00792   
00793   double x1 = std::cos(phi_window.first);
00794   double x2 = std::cos(phi_window.second);
00795   double y1 = std::sin(phi_window.first);
00796   double y2 = std::sin(phi_window.second);
00797   double xp = std::cos(get_phi());
00798   double yp = std::sin(get_phi());
00799 
00800   double r1 = std::sqrt(MUIOO::SQUARE(x1) + MUIOO::SQUARE(y1));
00801   double r2 = std::sqrt(MUIOO::SQUARE(x2) + MUIOO::SQUARE(y2));
00802   double rp = std::sqrt(MUIOO::SQUARE(xp) + MUIOO::SQUARE(yp));
00803   
00804   double dphi_window = std::acos((x1*x2 + y1*y2)/(r1*r2));
00805   double dphi_left = std::acos((x1*xp + y1*yp)/(r1*rp));
00806   double dphi_right = std::acos((x2*xp + y2*yp)/(r2*rp));
00807   
00808   
00809   
00810   
00811   return (dphi_left < dphi_window && dphi_right < dphi_window);
00812 }
00813 
00814 void 
00815 TMuiRoadFinder::Road::initialize_evaluation()
00816 { 
00817   if(_evaluation) return;
00818 
00819   _file = (TFile*)gROOT->GetListOfFiles()->FindObject("muioo_eval_ntuple.root");
00820   if (_file) {
00821     MUIOO::TRACE("TMuiRoadFinder::Road::initialize_evaluation, creating eval root file");
00822     _file = new TFile("muioo_eval_ntuple.root", "RECREATE");
00823   }
00824 
00825   
00826   
00827   _ntuple = new TNtuple("road_cluster","road_cluster","arm:plane:panel:orientation:ncoord:added:phi_check:theta_check:dca_dist:prox_dist:x:y:z:phi1:phi2:theta1:theta2");
00828   cout << " TMuiRoadFinder::Road::initialize_evaluation() ntuple created" << endl; 
00829   
00830   _evaluation = true;
00831   
00832   return;
00833 }
00834 void 
00835 TMuiRoadFinder::Road::finish_evaluation()
00836 {  
00837   if(_ntuple) delete _ntuple;
00838   _evaluation = false;
00839 }
00840 
00841 
00842 std::list<TMuiClusterMapO::value_type>
00843 TMuiRoadFinder::get_coords_in_window(TMuiClusterMapO* cluster_map,
00844                                      UShort_t arm,
00845                                      const road_window& theta_window,
00846                                      const road_window& phi_window)
00847 {
00848   
00849   
00850   typedef std::list<TMuiClusterMapO::value_type> local_list_type;
00851   local_list_type local_list;
00852   
00853   TMuiClusterMapO::iterator cluster_iter = cluster_map->get(arm);
00854 
00855   while(TMuiClusterMapO::pointer cluster_ptr = cluster_iter.next()){
00856 
00857     WindowEnum phi_begin = 
00858       check_phi_window(cluster_ptr->get()->get_coord_begin(), phi_window);
00859     WindowEnum phi_end = 
00860       check_phi_window(cluster_ptr->get()->get_coord_end(), phi_window);
00861 
00862     
00863     
00864     
00865     bool in_phi_window = false;
00866     if((phi_begin == IN_WINDOW || phi_end == IN_WINDOW) ||
00867        (phi_begin == HIGH_WINDOW && phi_end == LOW_WINDOW) ||
00868        (phi_begin == LOW_WINDOW && phi_end == HIGH_WINDOW)) {
00869       in_phi_window = true;
00870     }
00871     
00872     WindowEnum theta_begin = 
00873       check_theta_window(cluster_ptr->get()->get_coord_begin(), theta_window);
00874     WindowEnum theta_end = 
00875       check_theta_window(cluster_ptr->get()->get_coord_end(), theta_window);
00876 
00877     
00878     
00879     
00880     bool in_theta_window = false;
00881     if((theta_begin == IN_WINDOW || theta_end == IN_WINDOW) ||
00882        (theta_begin == HIGH_WINDOW && theta_end == LOW_WINDOW) ||
00883        (theta_begin == LOW_WINDOW && theta_end == HIGH_WINDOW)) {
00884       in_theta_window = true;    
00885     }
00886 
00887     if(in_theta_window && in_phi_window) local_list.push_back(*cluster_ptr);
00888   }    
00889   return local_list;
00890 }
00891 
00892 
00893 TMuiRoadFinder::WindowEnum
00894 TMuiRoadFinder::check_phi_window(const PHPoint& point, 
00895                                  const TMuiRoadFinder::road_window&phi_window) 
00896 {
00897   
00898   PHSphPoint spherepoint;
00899   PHGeometry::cartesianToSpherical(point, spherepoint);
00900  
00901   
00902   
00903   double thisphi = spherepoint.getPhi();
00904   double dphi_right = phi_window.second - thisphi;
00905   double dphi_left = thisphi - phi_window.first;
00906   
00907 
00908   
00909   
00910   
00911   
00912   
00913   if (phi_window.second > 2*M_PI && point.getY() > 0) {
00914     dphi_right -= 2*M_PI;
00915   }
00916 
00917   
00918   
00919   
00920   
00921   
00922   
00923   
00924   if(dphi_left >= 0 && dphi_right >= 0){
00925     return IN_WINDOW;
00926   } else if(dphi_left < 0) {
00927     return LOW_WINDOW;
00928   } else if(dphi_right < 0) {
00929     return HIGH_WINDOW;
00930   } else {
00931     return HIGH_WINDOW; 
00932   }
00933 }
00934 
00935 TMuiRoadFinder::WindowEnum
00936 TMuiRoadFinder::check_theta_window(const PHPoint& point, 
00937                                    const TMuiRoadFinder::road_window& 
00938                                    theta_window) 
00939 { 
00940   
00941   PHSphPoint spherepoint;
00942   PHGeometry::cartesianToSpherical(point, spherepoint);
00943   double theta_p = spherepoint.getTheta();
00944   
00945   if(theta_p >= theta_window.first && theta_p <= theta_window.second){
00946     return IN_WINDOW;
00947   } else if(theta_p < theta_window.first) {
00948     return LOW_WINDOW;
00949   } else if(theta_p > theta_window.second) {
00950     return HIGH_WINDOW;
00951   } else {
00952     return HIGH_WINDOW; 
00953   }
00954 }
00955 
00956 void 
00957 TMuiRoadFinder::initialize_evaluation()
00958 {
00959   if(_evaluation) return;
00960 
00961   _file = (TFile*)gROOT->GetListOfFiles()->FindObject("muioo_eval_ntuple.root");
00962   if (_file) {
00963     MUIOO::TRACE("TMuiRoadFinder::initialize_evaluation, creating eval root file");
00964     _file = new TFile("muioo_eval_ntuple.root", "RECREATE");
00965   }
00966 
00967   
00968   
00969   _ntuple = new TNtuple("road","road",
00970                         "arm:iroad:iclust:mc_exist:mc_found:"
00971                         "true_hit:bg_hit:th_true:phi_true:th_win:ph_win");
00972   
00973   _evaluation = true;
00974   return;
00975 }
00976 
00977 void TMuiRoadFinder::finish_evaluation()
00978 {
00979   if(_ntuple) delete _ntuple;
00980   _evaluation=false;
00981   return;
00982 }
00983 
00984 void 
00985 TMuiRoadFinder::evaluate(PHCompositeNode* top_node)
00986 {
00987   TMuiRoadFinder::road_list& road_list = get_road_list();
00988   TMuiRoadFinder::road_list::iterator road_list_iter = road_list.begin();
00989   for(;road_list_iter!=road_list.end();++road_list_iter){
00990     float ntvar[20] = {0};
00991     
00992     ntvar[0] = road_list_iter->get_arm();
00993     ntvar[1] = road_list_iter->get_cluster_list().size();
00994     
00995     typedef TMuiRoadFinder::Road::cluster_list road_cluster_list;
00996     road_cluster_list& cluster_list = road_list_iter->get_cluster_list();
00997     road_cluster_list::iterator cluster_iter = cluster_list.begin();    
00998     for(;cluster_iter!=cluster_list.end();++cluster_iter){
00999       TMuiClusterMapO::const_key_iterator clus_iter = cluster_iter->get()->get_associated<TMuiClusterO>();
01000       if(!clus_iter.at_end()){
01001         TMuiHitMapO::const_key_iterator hit_iter = clus_iter->get()->get_associated<TMuiHitO>();
01002         while(TMuiHitMapO::const_pointer hit_ptr = hit_iter.next()){
01003           TMuiMCHitMapO::const_key_iterator mc_hit_iter = hit_ptr->get()->get_associated<TMuiMCHitO>();
01004           if(!mc_hit_iter.at_end()){
01005           }
01006         }
01007       }
01008     }
01009   }
01010 }
01011 
01012 
01013