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