Main Page   Modules   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

mMuiFindRoad.cxx

Go to the documentation of this file.
00001 
00002 //
00003 // Utility class: mMuiFindRoad:
00004 // Description: Associate TMuiCluster's with TMuiRoad
00005 //              
00007 
00008 // MUIOO headers
00009 //
00010 #include <mMuiFindRoad.h>
00011 #include <mMuiFindRoadPar.h>
00012 #include <TMuiChannelId.hh>
00013 #include <TMutNode.h>
00014 #include <TMutGeo.h>
00015 #include <PHException.h>
00016 #include <PHGeometry.h>
00017 
00018 // STL/BOOST/GSL
00019 //
00020 #include <gsl/gsl_fit.h>
00021 #include <cmath>
00022 #include <iostream>
00023 #include <string>
00024 #include <list>
00025 #include <boost/array.hpp>
00026 
00031 mMuiFindRoad::mMuiFindRoad() : 
00032   _timer( PHTimeServer::get()->insert_new( "mMuiFindRoad" ) )
00033 {
00034   name = "mMuiFindRoad";
00035   MUIOO::TRACE("initializing module " + std::string(name.getString()));  
00036 }
00037 
00041 mMuiFindRoad::~mMuiFindRoad() { }
00042 
00046 PHBoolean mMuiFindRoad::event(PHCompositeNode* top_node)
00047 {
00048   
00049   _timer.get()->restart(); 
00050   
00051   try { 
00052 
00053     // Reset IOC pointers
00054     //
00055     set_interface_ptrs(top_node);
00056 
00057     // Find Roads using chosen algorithm
00058     //
00059     find_roads();
00060     
00061     // Do the associations
00062     //
00063     associate_clusters();
00064     
00065     // Do a final fit, now after everything is settled
00066     //
00067     fit_roads();
00068 
00069     // Set road parameters that have not yet been set
00070     //
00071     set_road_parameters();
00072 
00073     // Apply road cuts - done in TMuiRoadFinder; not much too add here yet
00074     //
00075     //apply_road_cuts();
00076     
00077     // Eliminate duplicate roads
00078     //
00079     //eliminate_duplicates();
00080     
00081   } 
00082   catch(std::exception& e) {
00083     
00084     MUIOO::TRACE(e.what());
00085     return False;
00086   }  
00087   
00088   // If verbose dump the contents of the cluster map
00089   //
00090   _timer.get()->stop();
00091   if(_mod_par->get_verbosity() >= MUIOO::ALOT) _road_map->print();
00092   if(_mod_par->get_verbosity() >= MUIOO::SOME) _timer.get()->print();     
00093   
00094   return True;
00095 }
00096 
00100 void mMuiFindRoad::set_interface_ptrs(PHCompositeNode* top_node){  
00101   
00102   // module runtime parameters
00103   //
00104   _mod_par = TMutNode<mMuiFindRoadPar>::find_node(top_node,"mMuiFindRoadPar");
00105   
00106   // TMuiCluster IOC
00107   //
00108   _cluster_map = TMutNode<TMuiClusterMapO>::find_node(top_node,"TMuiClusterMapO");
00109   // TMuiRoad IOC
00110   //
00111   _road_map = TMutNode<TMuiRoadMapO>::find_node(top_node,"TMuiRoadMapO");
00112 } 
00113 
00114 void 
00115 mMuiFindRoad::find_roads()
00116 {
00117   /*
00118     cout << "mMuiFindRoad::find_roads() mod-par dump" << endl;
00119     _mod_par->print();
00120   */
00121   // The road finding algorithm is encapsulated in TMuiRoadFinder
00122   //
00123   TMuiRoadFinder road_finder;
00124   // 
00125   // some parameters are hardwired as statics into TMuiRoadFinder
00126   // use parameter file to set them
00127   road_finder.set_dca_cut(_mod_par->get_coord_dca_cut());
00128   road_finder.set_prox_cut(_mod_par->get_coord_proximity_cut());
00129   road_finder.set_min_cluster(_mod_par->get_min_cluster());
00130   road_finder.set_min_point(_mod_par->get_min_point());
00131   if (_mod_par->get_mode() == mMuiFindRoadPar::NO_REVERSE) {
00132     road_finder.set_reversed_algo(false);
00133   }
00134   else {
00135     road_finder.set_reversed_algo(true);
00136   }
00137   // window usage
00138   bool use_window = _mod_par->get_use_window();
00139   TMuiRoadFinder::road_window phi_window = std::make_pair(0,0);
00140   TMuiRoadFinder::road_window theta_window = std::make_pair(0,0);
00141   if (use_window) {
00142     // set ranges of phi and theta windows
00143     // the windows are centered by TMuiRoadFinder
00144     // when starting a road
00145     phi_window.first -= 0.5 * _mod_par->get_phi_window();
00146     theta_window.first -= 0.5 * _mod_par->get_theta_window();
00147     phi_window.second += 0.5 * _mod_par->get_phi_window();
00148     theta_window.second += 0.5 * _mod_par->get_theta_window();
00149   }
00150 
00151   // Clear local list
00152   //
00153   _roads.clear();
00154   
00155   // Loop over all/both arms and envoke the road finder if given
00156   // arm has hits.
00157   //
00158   for(int arm=0; arm<MUIOO::NumberOfArms;++arm) {
00159     if(_cluster_map->get(arm).count()){
00160       road_finder.find(_cluster_map, arm,
00161                        use_window, phi_window, theta_window);
00162       // Splice all roads found in this section into local list
00163       //
00164       _roads.splice(_roads.end(), road_finder.get_road_list());
00165     }
00166   }
00167   
00168   // Get the list of roads found by the algorithm and instantiate an IOC
00169   // for those found.
00170   //
00171   TMuiRoadFinder::road_list::const_iterator road_list_iter = _roads.begin();
00172   for(;road_list_iter!=_roads.end();++road_list_iter){
00173     
00174     if(_mod_par->get_verbosity() == MUIOO::ALOT) road_list_iter->print();
00175     
00176     TMuiRoadMapO::iterator road_iter = _road_map->insert_new(road_list_iter->get_arm());
00177     // Seed the full fit with road parameters
00178     //
00179     road_iter->get()->set_fit_par(road_list_iter->get_fit_par());
00180   }
00181 }
00182 
00183 void 
00184 mMuiFindRoad::associate_clusters()
00185 {
00186   // Loop over TMuiRoad [
00187   //  Loop over TMuiCluster in same arm
00188   //    It cluster is close enough to extrapolated
00189   //    road, then call associate_cluster(..)
00190   //  ]
00191   // ]
00192 
00193   // Get an iterator to all roads
00194   //
00195   TMuiRoadMapO::iterator road_iter = _road_map->range();
00196   while(TMuiRoadMapO::pointer road_ptr = road_iter.next()){             
00197     
00198     UShort_t arm = road_ptr->get()->get_arm();
00199     
00200     // Get an iterator to all TMuiCluster in same arm
00201     //
00202     TMuiClusterMapO::iterator cluster_iter = _cluster_map->get(arm);
00203     while(TMuiClusterMapO::pointer cluster_ptr = cluster_iter.next()){                
00204       // Extract the z, PHLine and road parameters
00205       //
00206       PHLine line = cluster_ptr->get()->get_coord();    
00207       double z_cluster = cluster_ptr->get()->get_centroidpos().getZ();       
00208       const TMutFitPar* fit_par = road_ptr->get()->get_const_fitpar();
00209       
00210       // Calculate distance form TMuiCluster to extrapolated road
00211       //
00212       PHPoint trk_point = TMutTrackUtil::linear_track_model(fit_par,z_cluster);
00213       double distance = PHGeometry::distanceLinePoint(line,trk_point);
00214       
00215       // If the cluster is close enough to the extrapolated Road then associate
00216       //
00217       if(distance < _mod_par->get_coord_proximity_cut()){
00218         associate_cluster(road_ptr,cluster_ptr,trk_point,distance);
00219       }
00220     }
00221   }
00222 }
00223 
00224 void
00225 mMuiFindRoad::associate_cluster(TMuiRoadMapO::pointer road_ptr,
00226                                 TMuiClusterMapO::pointer in_cluster_ptr,
00227                                 const PHPoint& trk_point,
00228                                 double in_distance)
00229 {
00230   // Loop over TMuiCluster associated with this road
00231   //   if we find a cluster at same locations as input [
00232   //    if new cluster is closer [
00233   //      remove old association
00234   //      associate new cluster
00235   //      return
00236   //    ] else [
00237   //      do nothing
00238   //      return
00239   //   ]
00240   // ]
00241   //
00242   // (if we get here no previous association in this location exists)
00243   // Associate road and cluster
00244   //
00245   TMuiClusterMapO::key_iterator cluster_iter = road_ptr->get()->get_associated<TMuiClusterO>();
00246   while(TMuiClusterMapO::pointer cluster_ptr = cluster_iter.next()){
00247     
00248     // Check for existing TMuiCluster at this location and keep the closest one.
00249     //
00250     if(cluster_ptr->get()->get_plane() ==  in_cluster_ptr->get()->get_plane()
00251 && cluster_ptr->get()->get_orientation() ==  in_cluster_ptr->get()->get_orientation()) {
00252       
00253       double distance = PHGeometry::distanceLinePoint(cluster_ptr->get()->get_coord(),trk_point);
00254       // Keep the old one.
00255       //
00256       if(distance < in_distance) {
00257         return;
00258       } else {
00259         // Keep the new one, remove the old one.
00260         //
00261         PHKey::disassociate(road_ptr,cluster_ptr);
00262         PHKey::associate(road_ptr, in_cluster_ptr);
00263         return;
00264       }
00265     } 
00266   }
00267   // No existing cluster at this location
00268   //
00269   PHKey::associate(road_ptr, in_cluster_ptr);
00270 }
00271 
00272 void
00273 mMuiFindRoad::fit_roads()
00274 {
00275   // Here we'll do a final fit after all associations 
00276   // and include all clusters in the fit
00277   // Get an iterator to all roads
00278   //
00279   TMuiRoadMapO::iterator road_iter = _road_map->range();
00280   while(TMuiRoadMapO::pointer road_ptr = road_iter.next()) {            
00281 
00282     TMutFitPar fit_par = road_ptr->get()->get_fit_par();          
00283 
00284     // Iterator for all clusters associated to this road
00285     TMuiClusterMapO::const_key_iterator clust_iter = 
00286       road_ptr->get()->get_associated<TMuiClusterO>();
00287 
00288     // arrays for cluster info
00289     // The second argument is the array dimension
00290     // horizontal
00291     int n_h = 0;
00292     boost::array<double,MUIOO::MAX_PLANE> hx = {{0}}; 
00293     boost::array<double,MUIOO::MAX_PLANE> hy = {{0}}; 
00294     boost::array<double,MUIOO::MAX_PLANE> hz = {{0}}; 
00295     // vertical
00296     int n_v = 0;
00297     boost::array<double,MUIOO::MAX_PLANE> vx = {{0}}; 
00298     boost::array<double,MUIOO::MAX_PLANE> vy = {{0}}; 
00299     boost::array<double,MUIOO::MAX_PLANE> vz = {{0}}; 
00300 
00301     double z0 = road_ptr->get()->get_gap0_point().getZ();
00302 
00303     // use constants from float.h to really init min/max properly
00304     double z_max = -DBL_MAX; 
00305     double z_min = DBL_MAX;
00306 
00307     while(TMuiClusterMapO::const_pointer clust_ptr = clust_iter.next()) {
00308 
00309       PHPoint cpos = clust_ptr->get()->get_centroidpos();
00310       z_min = std::min(z_min,cpos.getZ());
00311       z_max = std::max(z_max,cpos.getZ());
00312       if (clust_ptr->get()->get_orientation() == kHORIZ) {
00313         if (n_h >= MUIOO::MAX_PLANE) {
00314           MUIOO::TRACE(" too many horizontal clusters associated to road");  
00315         }
00316         hx.at(n_h) = cpos.getX();
00317         hy.at(n_h) = cpos.getY();
00318         hz.at(n_h) = cpos.getZ() - z0;
00319         n_h++;
00320       }
00321       else { // vertical
00322         if (n_v >= MUIOO::MAX_PLANE) {
00323           MUIOO::TRACE(" too many vertical clusters associated to road");  
00324         }
00325         vx.at(n_v) = cpos.getX();
00326         vy.at(n_v) = cpos.getY();
00327         vz.at(n_v) = cpos.getZ() - z0;
00328         n_v++;
00329       }
00330     }
00331       
00332     double x0=0,m_x=0, y0=0, m_y=0;
00333     double hcov00=0, hcov11=0, hcov22=0;
00334     double vcov00=0, vcov11=0, vcov22=0;
00335     double chi2x=0, chi2y=0;
00336       
00337     // Fit x: method from gsl_fit.h
00338     // use vertical info
00339     gsl_fit_linear(vz.begin(),1,vx.begin(),1,n_v,
00340                    &x0,&m_x,&vcov00,&vcov11,&vcov22,&chi2x);
00341       
00342     // Fit y
00343     // use horizontal info
00344     gsl_fit_linear(hz.begin(),1,hy.begin(),1,n_h,
00345                    &y0,&m_y,&hcov00,&hcov11,&hcov22,&chi2y);
00346 
00347     // no sanity check made on results - let's just store them
00348     fit_par.set_x(x0);
00349     fit_par.set_y(y0);
00350     fit_par.set_z(z0);
00351     fit_par.set_dxdz(m_x);
00352     fit_par.set_dydz(m_y);
00353     
00354     // for the covariance part, we don't need to use all the 4x4 space
00355     // in TMutFitPar, 2*3 is enough; first horizontal and then vertical info
00356     fit_par.set_covar(kHORIZ, 0, hcov00);
00357     fit_par.set_covar(kHORIZ, 1, hcov11);
00358     fit_par.set_covar(kHORIZ, 2, hcov22);
00359     fit_par.set_covar(kVERT, 0, vcov00);
00360     fit_par.set_covar(kVERT, 1, vcov11);
00361     fit_par.set_covar(kVERT, 2, vcov22);
00362 
00363     // chi-sq and degrees of freedom
00364     double chisq = chi2x + chi2y; 
00365     size_t ndof = n_h + n_v - 2*2;
00366     if (ndof > 0) { 
00367       chisq /= ndof;
00368       road_ptr->get()->set_road_quality(chisq);
00369     }
00370     else { 
00371       road_ptr->get()->set_road_quality(0.0); 
00372     }
00373     road_ptr->get()->set_freedom(ndof);
00374     fit_par.set_chi_square(chisq);
00375 
00376     // "begin" is closest to interaction region
00377     //
00378     if(road_ptr->get()->get_arm() == MUIOO::South) {
00379       fit_par.set_z_begin(z_max) ;
00380       fit_par.set_z_end(z_min);
00381     } 
00382     else {
00383       fit_par.set_z_begin(z_min) ;
00384       fit_par.set_z_end(z_max);
00385     }
00386     road_ptr->get()->set_fit_par(fit_par);
00387   }
00388 
00389   return;
00390 }
00391 
00392 void
00393 mMuiFindRoad::set_road_parameters()
00394 {
00395   // The parameters that have been set so far is basically 
00396   // just which clusters belong to it and what the fit parameters
00397   // are.  freedom and road_quality should be set in fit_roads() 
00398   // Not set variables are
00399   // nhit - number of clusters in both orientations
00400   // depth - last plane hit
00401   // gapbit - bit coding of which gap/plane and orientation had a hit 
00402   // max_hit_plane - maximum hits associated per plane?
00403   // ghost_flag 
00404   // group
00405   // golden
00406   //
00407   // The last three of these are not too relevant for this roadfinder
00408   // and we'll leave them as  their init values.
00409   // The ones with ?, I'm not exactly sure of the meaning of 
00410   // (previously not set in standard road finder: mMuiRoadFinder1)
00411 
00412   // Get an iterator to all roads
00413   //
00414   TMuiRoadMapO::iterator road_iter = _road_map->range();
00415   while(TMuiRoadMapO::pointer road_ptr = road_iter.next()) {            
00416 
00417     // Iterator for all clusters associated to this road
00418     TMuiClusterMapO::const_key_iterator clust_iter = 
00419       road_ptr->get()->get_associated<TMuiClusterO>();
00420 
00421     road_ptr->get()->set_nhit(clust_iter.count());
00422 
00423 
00424     UShort_t depth = 0;
00425     UShort_t gapbit = 0;
00426     UShort_t hits_plane[MUIOO::MAX_PLANE] = {0};
00427 
00428     while(TMuiClusterMapO::const_pointer clust_ptr = clust_iter.next()) {
00429 
00430       if (depth < clust_ptr->get()->get_plane()) {
00431         depth = clust_ptr->get()->get_plane();
00432       }
00433       gapbit=gapbit | (clust_ptr->get()->get_plane() << 
00434                        (MUIOO::MAX_PLANE*clust_ptr->get()->get_orientation()));
00435       hits_plane[clust_ptr->get()->get_plane()]++;      
00436     }
00437     road_ptr->get()->set_depth(depth);
00438     road_ptr->get()->set_gapbit(gapbit);
00439     UShort_t max_hit_plane = 0;
00440     for (int plane = 0; plane<MUIOO::MAX_PLANE; plane++) {
00441       if (max_hit_plane < hits_plane[plane]) {
00442         max_hit_plane = hits_plane[plane];
00443       }
00444     }
00445     road_ptr->get()->set_max_hit_plane(max_hit_plane);
00446   }
00447   return;
00448 }
00449 
00450 void
00451 mMuiFindRoad::apply_road_cuts()
00452 {  
00453   // Here we punt on roads that don't have a minimum number of associated
00454   // TMuiCluster.
00455   //
00456   TMuiRoadMapO::iterator road_iter = _road_map->range();
00457   while(TMuiRoadMapO::pointer road_ptr = road_iter.next()){
00458     // Minimum hits/cluster cut
00459     //
00460     if(road_ptr->get()->get_nhit() < _mod_par->get_min_cluster()) { 
00461       _road_map->erase(road_ptr->get()->get_key());
00462     } 
00463   }
00464 }
00465 
00466 void
00467 mMuiFindRoad::eliminate_duplicates()
00468 {
00469   typedef std::vector<TMuiRoadMapO::value_type> cluster_list;
00470   cluster_list remove_list;
00471   TMuiRoadMapO::iterator road_iter = _road_map->range();
00472   while(TMuiRoadMapO::pointer road_ptr = road_iter.next()){
00473     TMuiRoadMapO::iterator road_iter2 = road_iter;
00474     ++road_iter2;
00475     while(TMuiRoadMapO::pointer road_ptr2 = road_iter2.next()) {
00476       if(cluster_list_equal(road_ptr, road_ptr2)) {
00477         remove_list.push_back(*road_ptr2);
00478       }
00479     }
00480   }
00481   
00482   cluster_list::iterator remove_iter = remove_list.begin();
00483   for(;remove_iter != remove_list.end(); ++remove_iter){
00484     _road_map->erase(remove_iter->get()->get_key());
00485   } 
00486 }
00487 
00488 bool
00489 mMuiFindRoad::cluster_list_equal(const TMuiRoadMapO::pointer road1,
00490                                  const TMuiRoadMapO::pointer road2) 
00491 {
00492   TMuiClusterMapO::key_iterator road1_iter = road1->get()->get_associated<TMuiClusterO>();  
00493   TMuiClusterMapO::key_iterator road2_iter = road1->get()->get_associated<TMuiClusterO>();  
00494   if(road1_iter.count() != road2_iter.count()) return false;
00495   while(TMuiClusterMapO::pointer road1_ptr = road1_iter.next()){
00496     bool match = false;
00497     road2_iter = road2->get()->get_associated<TMuiClusterO>();
00498     while(TMuiClusterMapO::pointer road2_ptr = road2_iter.next()){
00499       if(road1_ptr->get()->get_key() == road2_ptr->get()->get_key()) {
00500         match = true;
00501       }
00502     }
00503     if(!match) return false;
00504   }
00505   return true;
00506 }
00507 
00508 
00509 
00510 
00511 
00512 

MUIOO: PHENIX Muon Identifier Analysis Framework. Documentation by doxygen
Last modified: