All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ClusterPCA_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // ClusterPCA class
4 //
5 // This algorithm is designed to find the principal axis and diffuseness
6 // of clusters
7 //
8 ////////////////////////////////////////////////////////////////////////
9 
10 #include <string>
11 #include <array>
12 
13 //Framework includes:
14 #include "messagefacility/MessageLogger/MessageLogger.h"
15 #include "fhiclcpp/ParameterSet.h"
16 #include "canvas/Persistency/Common/Ptr.h"
17 #include "art/Framework/Core/EDAnalyzer.h"
18 #include "art/Framework/Core/ModuleMacros.h"
19 #include "canvas/Persistency/Common/FindManyP.h"
20 #include "art/Framework/Principal/Event.h"
21 #include "art/Framework/Principal/Handle.h"
22 #include "art/Framework/Services/Registry/ServiceHandle.h"
23 #include "art_root_io/TFileService.h"
24 
25 //LArSoft includes:
29 
30 // Root includes
31 #include "TPrincipal.h"
32 #include "TTree.h"
33 
34 
35 
36 namespace cluster {
37 
38  class ClusterPCA : public art::EDAnalyzer {
39 
40  public:
41 
42  explicit ClusterPCA(fhicl::ParameterSet const& pset);
43  ~ClusterPCA();
44 
45  private:
46 
47  void PerformClusterPCA(const std::vector<art::Ptr<recob::Hit> >& HitsThisCluster, double* PrincDirectionWT, double& PrincValue, double& TotalCharge, bool NormPC);
48 
49  void analyze(art::Event const& evt);
50  void beginJob();
51 
52  std::string fClusterModuleLabel;
53  bool fNormPC;
54 
55  TTree * fTree;
56 
57  Int_t fView;
58  Float_t fPrincDirW;
59  Float_t fPrincDirT;
60  Float_t fPrincValue;
61  Float_t fTotalCharge;
62  Float_t fNHits;
63 
64  }; // class ClusterPCA
65 
66 }
67 
68 //#endif
69 
70 
71 
72 namespace cluster{
73 
74  //-------------------------------------------------
75  ClusterPCA::ClusterPCA(fhicl::ParameterSet const& pset)
76  : EDAnalyzer(pset)
77  , fClusterModuleLabel(pset.get<std::string>("ClusterModuleLabel"))
78  , fNormPC (pset.get<bool>("NormPC"))
79  {
80  }
81 
82  //-------------------------------------------------
84  {
85  }
86 
87  //-------------------------------------------------
88  // Set up analysis tree
90  {
91  art::ServiceHandle<art::TFileService const> tfs;
92  fTree = tfs->make<TTree>("PCATree","PCATree");
93  fTree->Branch("View", &fView, "View/I");
94  fTree->Branch("PrincDirW", &fPrincDirW, "PrincDirW/F");
95  fTree->Branch("PrincDirT", &fPrincDirT, "PrincDirT/F");
96  fTree->Branch("PrincValue",&fPrincValue, "PrincValue/F");
97  fTree->Branch("TotalCharge",&fTotalCharge, "TotalCharge/F");
98  fTree->Branch("NHits", &fNHits, "fNHits/F");
99  }
100 
101  //------------------------------------------------------------------------------------//
102  void ClusterPCA::analyze(art::Event const& evt)
103  {
104  // Get a Handle for the input Cluster object(s).
105  art::Handle< std::vector<recob::Cluster> > clusterVecHandle;
106  evt.getByLabel(fClusterModuleLabel,clusterVecHandle);
107 
108  constexpr size_t nViews = 3;
109 
110  // one vector of cluster index in the original collection, per view;
111  // to support all present views, replace with a dynamically growing array
112  std::array<std::vector<size_t>, nViews> ClsIndex;
113 
114  // loop over the input Clusters
115  for(size_t i = 0; i < clusterVecHandle->size(); ++i){
116 
117  //get a art::Ptr to each Cluster
118  art::Ptr<recob::Cluster> cl(clusterVecHandle, i);
119 
120  switch(cl->View()){
121  case geo::kU :
122  fView=0;
123  break;
124  case geo::kV :
125  fView=1;
126  break;
127  case geo::kZ :
128  fView=2;
129  break;
130  default :
131  mf::LogError("ClusterPCA")
132  << "Hit belongs to an unsupported view (#" << cl->View() << ")";
133  break;
134  }// end switch on view
135 
136  ClsIndex[fView].push_back(i);
137  }// end loop over input clusters
138 
139  art::FindManyP<recob::Hit> fm(clusterVecHandle, evt, fClusterModuleLabel);
140  for(fView = 0; fView < (int) nViews; ++fView){
141 
142  const std::vector<size_t>& ClsIndices = ClsIndex[fView];
143 
144  for(size_t c = 0; c < ClsIndices.size(); ++c){
145 
146  // find the hits associated with the current cluster
147  const std::vector<art::Ptr<recob::Hit>>& ptrvs = fm.at(ClsIndices[c]);
148 
149  double PrincDir[2], PrincValue=0;
150  double TotalCharge=0;
151 
152  PerformClusterPCA( ptrvs, PrincDir, PrincValue, TotalCharge, fNormPC);
153 
154  fPrincDirW = PrincDir[0];
155  fPrincDirT = PrincDir[1];
156  fPrincValue = PrincValue;
157  fTotalCharge = TotalCharge;
158  fNHits = ptrvs.size();
159 
160  fTree->Fill();
161 
162  }// end loop over first cluster iterator
163  }// end loop over planes
164 
165  return;
166 
167  } // ClusterPCA::analyze()
168 
169 
170 
171 
172 
173 
174 
175 
176 // Perform PCA analysis of the hits in a cluster.
177 //
178 // This method is supplied with the vector of ptrs to hits in the cluster.
179 //
180 // It returns 2 things:
181 // 1. the principal direction, in [w,t] coordinates.
182 // 2. the principal eigenvalue, which is a measure of colinearity
183 //
184 // There is also a flag which can be specified to determine whether to normalize the PCA.
185 // For NormPC=true direction finding is not properly handled yet (easy to fix later)
186 // It is not clear yet whether true or false is more effective for cluster showeriness studies.
187 
188  void ClusterPCA::PerformClusterPCA(const std::vector<art::Ptr<recob::Hit> >& HitsThisCluster, double* PrincipalDirection, double& PrincipalEigenvalue, double& TotalCharge, bool NormPC)
189  {
190 
191  double Center[2] = {0,0};
192  TotalCharge = 0;
193 
194  for(auto itHit = HitsThisCluster.begin(); itHit!=HitsThisCluster.end(); ++itHit)
195  {
196  Center[0] += (*itHit)->WireID().Wire;
197  Center[1] += (*itHit)->PeakTime();
198  TotalCharge += (*itHit)->Integral();
199  }
200 
201  Center[0] /= float(HitsThisCluster.size());
202  Center[1] /= float(HitsThisCluster.size());
203 
204 
205  double WireTime[2];
206 
207  std::string OptionString;
208 
209  if(NormPC==false)
210  OptionString = "D";
211  else
212  OptionString = "ND";
213 
214  TPrincipal pc(2, OptionString.c_str());
215 
216 
217  for(auto itHit = HitsThisCluster.begin(); itHit!=HitsThisCluster.end(); ++itHit)
218  {
219  WireTime[0] = (*itHit)->WireID().Wire - Center[0];
220  WireTime[1] = (*itHit)->PeakTime() - Center[1];
221 
222  pc.AddRow(WireTime);
223 
224  }
225 
226  pc.MakePrincipals();
227 
228  PrincipalEigenvalue = (*pc.GetEigenValues())[0];
229 
230  for(size_t n=0; n!=2; ++n)
231  {
232  PrincipalDirection[n]= (*pc.GetEigenVectors())[0][n];
233  }
234 
235 
236  // Comment this out if you want to shut it up
237  pc.Print("MSEV");
238 
239  pc.Clear();
240  return;
241 }
242 
243 
244 } // end namespace
245 
246 namespace cluster{
247 
248  DEFINE_ART_MODULE(ClusterPCA)
249 
250 } // end namespace
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
Definition: UtilFunc.cxx:42
process_name cluster
Definition: cheaterreco.fcl:51
Planes which measure V.
Definition: geo_types.h:130
Declaration of signal hit object.
static constexpr bool
Planes which measure Z direction.
Definition: geo_types.h:132
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
Planes which measure U.
Definition: geo_types.h:129
void analyze(art::Event const &evt)
std::string fClusterModuleLabel
Declaration of cluster object.
Definition of data types for geometry description.
void PerformClusterPCA(const std::vector< art::Ptr< recob::Hit > > &HitsThisCluster, double *PrincDirectionWT, double &PrincValue, double &TotalCharge, bool NormPC)
ClusterPCA(fhicl::ParameterSet const &pset)
art::ServiceHandle< art::TFileService > tfs
TCEvent evt
Definition: DataStructs.cxx:8