9 #include <calobase/RawCluster.h>
10 #include <calobase/RawClusterContainer.h>
11 #include <calobase/RawTowerGeom.h>
12 #include <calobase/RawTowerGeomContainer.h>
13 #include <calobase/RawClusterUtility.h>
26 #include <TLorentzVector.h>
28 #include <gsl/gsl_randist.h>
29 #include <gsl/gsl_rng.h>
37 return (a.second < b.second);
42 float deta = eta1 - eta2;
43 float dphi = phi1 - phi2;
44 while ( dphi > M_PI ) dphi -= 2 * M_PI;
45 while ( dphi < -M_PI ) dphi += 2 * M_PI;
46 return sqrt( pow( deta, 2 ) + pow( dphi ,2 ) );
55 std::pair<float, float> expected_signature( response , resolution );
57 return expected_signature;
64 _energy_match_Nsigma( 1.5 )
91 std::cout <<
"ParticleFlowReco::process_event with Nsigma = " <<
_energy_match_Nsigma << std::endl;
95 if (!pflowContainer) {
96 std::cout <<
" ERROR -- can't find ParticleFlowElements node after it should have been created" << std::endl;
101 int global_pflow_index = 0;
104 RawTowerGeomContainer *geomEM = findNode::getClass<RawTowerGeomContainer>(topNode,
"TOWERGEOM_CEMC");
105 RawTowerGeomContainer *geomIH = findNode::getClass<RawTowerGeomContainer>(topNode,
"TOWERGEOM_HCALIN");
106 RawTowerGeomContainer *geomOH = findNode::getClass<RawTowerGeomContainer>(topNode,
"TOWERGEOM_HCALOUT");
108 if ( !geomEM || !geomIH || !geomOH ) {
109 std::cout <<
"ParticleFlowReco::process_event : FATAL ERROR, cannot find tower geometry containers" << std::endl;
114 RawClusterContainer *clustersEM = findNode::getClass<RawClusterContainer>(topNode,
"TOPOCLUSTER_EMCAL");
115 RawClusterContainer *clustersHAD = findNode::getClass<RawClusterContainer>(topNode,
"TOPOCLUSTER_HCAL");
118 std::cout <<
"ParticleFlowReco::process_event : FATAL ERROR, cannot find cluster container TOPOCLUSTER_EMCAL" << std::endl;
121 if ( !clustersHAD ) {
122 std::cout <<
"ParticleFlowReco::process_event : FATAL ERROR, cannot find cluster container TOPOCLUSTER_HCAL" << std::endl;
157 GlobalVertexMap* vertexmap = findNode::getClass<GlobalVertexMap>(topNode,
"GlobalVertexMap");
162 if (!vertexmap->
empty())
164 vertex = (vertexmap->
begin()->second);
169 std::cout <<
"ParticleFlowReco::process_event : initial population of TRK, EM, HAD objects " << std::endl;
176 float ohcalradius = geomOH->get_radius();
178 for(
auto iter = trackmap->
begin(); iter != trackmap->
end(); ++iter)
185 if(fabs(track->
get_eta()) > 1.1)
190 std::cout <<
"Track with p= " << track->
get_p() <<
", eta / phi = "
236 float cluster_E = hiter->second->get_energy();
237 if ( cluster_E < 0.2 )
continue;
239 float cluster_phi = hiter->second->get_phi();
241 float cluster_theta = M_PI / 2.0 - atan2( hiter->second->get_z() , hiter->second->get_r() );
242 float cluster_eta = -1 * log( tan( cluster_theta / 2.0 ) );
256 if (
Verbosity() > 5 && cluster_E > 0.2 )
257 std::cout <<
" EM topoCluster with E = " << cluster_E <<
", eta / phi = " << cluster_eta <<
" / " << cluster_phi <<
" , nTow = " << hiter->second->getNTowers() << std::endl;
259 std::vector<float> this_cluster_tower_eta;
260 std::vector<float> this_cluster_tower_phi;
269 this_cluster_tower_phi.push_back( tower_geom->
get_phi() );
270 this_cluster_tower_eta.push_back( tower_geom->
get_eta() );
273 std::cout <<
"ParticleFlowReco::process_event : FATAL ERROR , EM topoClusters seem to contain HCal towers" << std::endl;
290 float cluster_E = hiter->second->get_energy();
291 if ( cluster_E < 0.2 )
continue;
293 float cluster_phi = hiter->second->get_phi();
295 float cluster_theta = M_PI / 2.0 - atan2( hiter->second->get_z() , hiter->second->get_r() );
296 float cluster_eta = -1 * log( tan( cluster_theta / 2.0 ) );
310 if (
Verbosity() > 5 && cluster_E > 0.2 )
311 std::cout <<
" HAD topoCluster with E = " << cluster_E <<
", eta / phi = " << cluster_eta <<
" / " << cluster_phi <<
" , nTow = " << hiter->second->getNTowers() << std::endl;
313 std::vector<float> this_cluster_tower_eta;
314 std::vector<float> this_cluster_tower_phi;
322 RawTowerGeom *tower_geom = geomIH->get_tower_geometry(iter->first);
324 this_cluster_tower_phi.push_back( tower_geom->
get_phi() );
325 this_cluster_tower_eta.push_back( tower_geom->
get_eta() );
330 RawTowerGeom *tower_geom = geomOH->get_tower_geometry(iter->first);
332 this_cluster_tower_phi.push_back( tower_geom->
get_phi() );
333 this_cluster_tower_eta.push_back( tower_geom->
get_eta() );
335 std::cout <<
"ParticleFlowReco::process_event : FATAL ERROR , HCal topoClusters seem to contain EM towers" << std::endl;
353 std::cout <<
"ParticleFlowReco::process_event : TRK -> EM and TRK -> HAD linking " << std::endl;
355 for (
unsigned int trk = 0; trk <
_pflow_TRK_p.size() ; trk++ ) {
361 float min_em_dR = 0.2;
362 int min_em_index = -1;
364 for (
unsigned int em = 0 ; em <
_pflow_EM_E.size() ; em++) {
368 if ( dR > 0.2 )
continue;
370 bool has_overlap =
false;
379 if ( dphi > M_PI ) dphi -= 2 * M_PI;
380 if ( dphi < -M_PI ) dphi += 2 * M_PI;
382 if ( fabs( deta ) < 0.025 * 2.5 && fabs( dphi ) < 0.025 * 2.5 ) {
392 std::cout <<
" -> possible match to EM " << em <<
" with dR = " << dR << std::endl;
399 std::cout <<
" -> no match to EM " << em <<
" (even though dR = " << dR <<
" )" << std::endl;
422 if ( min_em_index > -1 ) {
427 std::cout <<
" -> matched EM " << min_em_index <<
" with pt / eta / phi = " <<
_pflow_EM_E.at( min_em_index ) <<
" / " <<
_pflow_EM_eta.at( min_em_index ) <<
" / " <<
_pflow_EM_phi.at( min_em_index ) <<
", dR = " << min_em_dR;
434 std::cout <<
" -> no EM match! ( best dR = " << min_em_dR <<
" ) " << std::endl;
438 float min_had_dR = 0.2;
439 int min_had_index = -1;
440 float max_had_pt = 0;
443 for (
unsigned int had = 0 ; had <
_pflow_HAD_E.size() ; had++) {
447 if ( dR > 0.5 )
continue;
449 bool has_overlap =
false;
458 if ( dphi > M_PI ) dphi -= 2 * M_PI;
459 if ( dphi < -M_PI ) dphi += 2 * M_PI;
461 if ( fabs( deta ) < 0.1 * 1.5 && fabs( dphi ) < 0.1 * 1.5 ) {
471 std::cout <<
" -> possible match to HAD " << had <<
" with dR = " << dR << std::endl;
482 std::cout <<
" -> no match to HAD " << had <<
" (even though dR = " << dR <<
" )" << std::endl;
488 if ( min_had_index > -1 ) {
493 std::cout <<
" -> matched HAD " << min_had_index <<
" with pt / eta / phi = " <<
_pflow_HAD_E.at( min_had_index ) <<
" / " <<
_pflow_HAD_eta.at( min_had_index ) <<
" / " <<
_pflow_HAD_phi.at( min_had_index ) <<
", dR = " << min_had_dR << std::endl;
497 std::cout <<
" -> no HAD match! ( best dR = " << min_had_dR <<
" ) " << std::endl;
506 std::cout <<
"ParticleFlowReco::process_event : EM -> HAD linking " << std::endl;
508 for (
unsigned int em = 0; em <
_pflow_EM_E.size() ; em++ ) {
514 float min_had_dR = 0.2;
515 int min_had_index = -1;
516 float max_had_pt = 0;
518 for (
unsigned int had = 0 ; had <
_pflow_HAD_E.size() ; had++) {
521 if ( dR > 0.5 )
continue;
523 bool has_overlap =
false;
532 if ( dphi > M_PI ) dphi -= 2 * M_PI;
533 if ( dphi < -M_PI ) dphi += 2 * M_PI;
535 if ( fabs( deta ) < 0.1 * 1.5 && fabs( dphi ) < 0.1 * 1.5 ) {
545 std::cout <<
" -> possible match to HAD " << had <<
" with dR = " << dR << std::endl;
556 std::cout <<
" -> no match to HAD " << had <<
" (even though dR = " << dR <<
" )" << std::endl;
562 if ( min_had_index > -1 ) {
567 std::cout <<
" -> matched HAD with E / eta / phi = " <<
_pflow_HAD_E.at( min_had_index ) <<
" / " <<
_pflow_HAD_eta.at( min_had_index ) <<
" / " <<
_pflow_HAD_phi.at( min_had_index ) <<
", dR = " << min_had_dR << std::endl;
571 std::cout <<
" -> no HAD match! ( best dR = " << min_had_dR <<
" ) " << std::endl;
579 std::cout <<
"ParticleFlowReco::process_event : sequential TRK -> EM && EM -> HAD ==> TRK -> HAD matching " << std::endl;
581 for (
unsigned int trk = 0; trk <
_pflow_TRK_p.size() ; trk++ ) {
594 bool is_trk_matched_to_HAD =
false;
597 if ( had == existing_had ) is_trk_matched_to_HAD =
true;
601 if ( ! is_trk_matched_to_HAD ) {
607 std::cout <<
" -> sequential match to HAD " << had <<
" through EM " <<
j << std::endl;
620 std::cout <<
"ParticleFlowReco::process_event : resolve TRK(s) + EM(s) -> HAD systems " << std::endl;
622 for (
unsigned int had = 0; had <
_pflow_HAD_E.size() ; had++ ) {
632 float total_TRK_p = 0;
633 float total_expected_E = 0;
634 float total_expected_E_var = 0;
639 std::vector<RawCluster*> matchedEClusters;
671 float expected_E_mean = expected_signature.first;
672 float expected_E_sigma = expected_signature.second;
675 std::cout <<
" -> -> -> expected calo signature is " << expected_E_mean <<
" +/- " << expected_E_sigma << std::endl;
678 total_expected_E += expected_E_mean;
679 total_expected_E_var += pow( expected_E_sigma , 2 );
688 pflow->
set_px( tlv.Px() );
689 pflow->
set_py( tlv.Py() );
690 pflow->
set_pz( tlv.Pz() );
691 pflow->
set_e( tlv.E() );
695 pflow->
set_id( global_pflow_index );
696 pflow->
set_type( ParticleFlowElement::PFLOWTYPE::MATCHED_CHARGED_HADRON );
699 global_pflow_index++;
705 float total_expected_E_err = sqrt( total_expected_E_var );
708 std::cout <<
" -> Total track Sum p = " << total_TRK_p <<
" , expected calo Sum E = " << total_expected_E <<
" +/- " << total_expected_E_err <<
" , observed EM+HAD Sum E = " << total_EMHAD_E << std::endl;
713 if ( total_expected_E > total_EMHAD_E ) {
716 std::cout <<
" -> Expected E > Observed E, looking for additional potential TRK->EM matches" << std::endl;
718 std::map<int, float> additional_EMs;
727 std::cout <<
" -> -> TRK " << trk <<
" has " << addtl_matches <<
" additional matches! " << std::endl;
733 float existing_dR = 0.21;
747 std::vector< std::pair<int,float> > additional_EMs_vec;
749 for (
auto&
x : additional_EMs) {
750 additional_EMs_vec.push_back( std::pair<int,float>(
x.first ,
x.second ) );
756 std::cout <<
" -> Sorting the set of potential additional EMs " << std::endl;
761 while ( additional_EMs_vec.size() != 0 && total_expected_E > total_EMHAD_E ) {
763 int new_EM = additional_EMs_vec.at( 0 ).first;
766 std::cout <<
" -> adding EM " << new_EM <<
" ( dR = " << additional_EMs_vec.at( 0 ).second <<
" to the system (should not see it as orphan below)" << std::endl;
776 additional_EMs_vec.erase( additional_EMs_vec.begin() );
782 if ( n_EM_added > 0 ) {
783 std::cout <<
"After adding N = " << n_EM_added <<
" any additional EMs : " << std::endl;
784 std::cout <<
"-> Total track Sum p = " << total_TRK_p <<
" , expected calo Sum E = " << total_expected_E <<
" +/- " << total_expected_E_err <<
" , observed EM+HAD Sum E = " << total_EMHAD_E << std::endl;
787 std::cout <<
"No additional EMs found, continuing hypothesis check" << std::endl;
797 std::cout <<
" -> -> calo compatible within Nsigma = " <<
_energy_match_Nsigma <<
" , remove and keep tracks " << std::endl;
804 float residual_energy = total_EMHAD_E - total_expected_E;
807 std::cout <<
" -> -> calo not compatible, create leftover cluster with " << residual_energy << std::endl;
816 pflow->
set_px( tlv.Px() );
817 pflow->
set_py( tlv.Py() );
818 pflow->
set_pz( tlv.Pz() );
819 pflow->
set_e( tlv.E() );
823 pflow->
set_id( global_pflow_index );
824 pflow->
set_type( ParticleFlowElement::PFLOWTYPE::LEFTOVER_EM_PARTICLE );
827 global_pflow_index++;
836 std::cout <<
"ParticleFlowReco::process_event : resolve TRK(s) -> EM(s) ( + no HAD) systems " << std::endl;
838 for (
unsigned int em = 0; em <
_pflow_EM_E.size() ; em++ ) {
849 float total_TRK_p = 0;
850 float total_expected_E = 0;
851 float total_expected_E_var = 0;
869 float expected_E_mean = expected_signature.first;
870 float expected_E_sigma = expected_signature.second;
873 std::cout <<
" -> -> -> expected calo signature is " << expected_E_mean <<
" +/- " << expected_E_sigma << std::endl;
876 total_expected_E += expected_E_mean;
877 total_expected_E_var += pow( expected_E_sigma , 2 );
885 std::vector<RawCluster*> eclus;
888 pflow->
set_px( tlv.Px() );
889 pflow->
set_py( tlv.Py() );
890 pflow->
set_pz( tlv.Pz() );
891 pflow->
set_e( tlv.E() );
895 pflow->
set_id( global_pflow_index );
896 pflow->
set_type( ParticleFlowElement::PFLOWTYPE::MATCHED_CHARGED_HADRON );
899 global_pflow_index++;
904 float total_expected_E_err = sqrt( total_expected_E_var );
907 std::cout <<
" -> Total track Sum p = " << total_TRK_p <<
" , expected calo Sum E = " << total_expected_E <<
" +/- " << total_expected_E_err <<
" , observed EM Sum E = " << total_EM_E << std::endl;
913 std::cout <<
" -> -> calo compatible within Nsigma = " <<
_energy_match_Nsigma <<
" , remove and keep tracks " << std::endl;
920 float residual_energy = total_EM_E - total_expected_E;
923 std::cout <<
" -> -> calo not compatible, create leftover cluster with " << residual_energy << std::endl;
932 std::vector<RawCluster*> eclus;
935 pflow->
set_px( tlv.Px() );
936 pflow->
set_py( tlv.Py() );
937 pflow->
set_pz( tlv.Pz() );
938 pflow->
set_e( tlv.E() );
942 pflow->
set_id( global_pflow_index );
943 pflow->
set_type( ParticleFlowElement::PFLOWTYPE::LEFTOVER_EM_PARTICLE );
946 global_pflow_index++;
955 std::cout <<
"ParticleFlowReco::process_event : remove TRK-unlinked EMs and HADs " << std::endl;
957 for (
unsigned int em = 0; em <
_pflow_EM_E.size() ; em++ ) {
972 std::vector<RawCluster*> eclus;
975 pflow->
set_px( tlv.Px() );
976 pflow->
set_py( tlv.Py() );
977 pflow->
set_pz( tlv.Pz() );
978 pflow->
set_e( tlv.E() );
982 pflow->
set_id( global_pflow_index );
983 pflow->
set_type( ParticleFlowElement::PFLOWTYPE::UNMATCHED_EM_PARTICLE );
986 global_pflow_index++;
991 for (
unsigned int had = 0; had <
_pflow_HAD_E.size() ; had++ ) {
1006 pflow->
set_px( tlv.Px() );
1007 pflow->
set_py( tlv.Py() );
1008 pflow->
set_pz( tlv.Pz() );
1009 pflow->
set_e( tlv.E() );
1013 pflow->
set_id( global_pflow_index );
1014 pflow->
set_type( ParticleFlowElement::PFLOWTYPE::UNMATCHED_NEUTRAL_HADRON );
1017 global_pflow_index++;
1022 for (
unsigned int trk = 0; trk <
_pflow_TRK_p.size() ; trk++ ) {
1037 pflow->
set_px( tlv.Px() );
1038 pflow->
set_py( tlv.Py() );
1039 pflow->
set_pz( tlv.Pz() );
1040 pflow->
set_e( tlv.E() );
1044 pflow->
set_id( global_pflow_index );
1045 pflow->
set_type( ParticleFlowElement::PFLOWTYPE::UNMATCHED_CHARGED_HADRON );
1048 global_pflow_index++;
1054 std::cout <<
"ParticleFlowReco::process_event: summary of PFlow objects " << std::endl;
1058 hiter->second->identify();
1074 std::cout <<
PHWHERE <<
"DST Node missing, doing nothing." << std::endl;
1083 dstNode->
addNode( pflowNode );
1087 ParticleFlowElementContainer *pflowElementContainer = findNode::getClass<ParticleFlowElementContainer>(topNode,
"ParticleFlowElements");
1088 if (!pflowElementContainer)
1092 pflowNode->
addNode( pflowElementNode );
1096 std::cout <<
PHWHERE <<
"::ERROR - ParticleFlowElements node alerady exists, but should not" << std::endl;
1108 std::cout <<
"ParticleFlowReco::ResetEvent(PHCompositeNode *topNode) Resetting internal structures, prepare for next event" << std::endl;
1118 std::cout <<
"ParticleFlowReco::EndRun(const int runnumber) Ending Run for Run " << runnumber << std::endl;
1128 std::cout <<
"ParticleFlowReco::End(PHCompositeNode *topNode) This is the End..." << std::endl;
1138 std::cout <<
"ParticleFlowReco::Reset(PHCompositeNode *topNode) being Reset" << std::endl;
1146 std::cout <<
"ParticleFlowReco::Print(const std::string &what) const Printing info for " << what << std::endl;