LArSoft  v09_90_00
Liquid Argon Software toolkit - https://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 <array>
11 #include <string>
12 
13 //Framework includes:
19 #include "art_root_io/TFileService.h"
22 #include "fhiclcpp/ParameterSet.h"
24 
25 //LArSoft includes:
29 
30 // Root includes
31 #include "TPrincipal.h"
32 #include "TTree.h"
33 
34 namespace cluster {
35 
36  class ClusterPCA : public art::EDAnalyzer {
37 
38  public:
39  explicit ClusterPCA(fhicl::ParameterSet const& pset);
40  ~ClusterPCA();
41 
42  private:
43  void PerformClusterPCA(const std::vector<art::Ptr<recob::Hit>>& HitsThisCluster,
44  double* PrincDirectionWT,
45  double& PrincValue,
46  double& TotalCharge,
47  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 namespace cluster {
71 
72  //-------------------------------------------------
74  : EDAnalyzer(pset)
75  , fClusterModuleLabel(pset.get<std::string>("ClusterModuleLabel"))
76  , fNormPC(pset.get<bool>("NormPC"))
77  {}
78 
79  //-------------------------------------------------
81 
82  //-------------------------------------------------
83  // Set up analysis tree
85  {
87  fTree = tfs->make<TTree>("PCATree", "PCATree");
88  fTree->Branch("View", &fView, "View/I");
89  fTree->Branch("PrincDirW", &fPrincDirW, "PrincDirW/F");
90  fTree->Branch("PrincDirT", &fPrincDirT, "PrincDirT/F");
91  fTree->Branch("PrincValue", &fPrincValue, "PrincValue/F");
92  fTree->Branch("TotalCharge", &fTotalCharge, "TotalCharge/F");
93  fTree->Branch("NHits", &fNHits, "fNHits/F");
94  }
95 
96  //------------------------------------------------------------------------------------//
98  {
99  // Get a Handle for the input Cluster object(s).
100  art::Handle<std::vector<recob::Cluster>> clusterVecHandle;
101  evt.getByLabel(fClusterModuleLabel, clusterVecHandle);
102 
103  constexpr size_t nViews = 3;
104 
105  // one vector of cluster index in the original collection, per view;
106  // to support all present views, replace with a dynamically growing array
107  std::array<std::vector<size_t>, nViews> ClsIndex;
108 
109  // loop over the input Clusters
110  for (size_t i = 0; i < clusterVecHandle->size(); ++i) {
111 
112  //get a art::Ptr to each Cluster
113  art::Ptr<recob::Cluster> cl(clusterVecHandle, i);
114 
115  switch (cl->View()) {
116  case geo::kU: fView = 0; break;
117  case geo::kV: fView = 1; break;
118  case geo::kZ: fView = 2; break;
119  default:
120  mf::LogError("ClusterPCA") << "Hit belongs to an unsupported view (#" << cl->View() << ")";
121  break;
122  } // end switch on view
123 
124  ClsIndex[fView].push_back(i);
125  } // end loop over input clusters
126 
127  art::FindManyP<recob::Hit> fm(clusterVecHandle, evt, fClusterModuleLabel);
128  for (fView = 0; fView < (int)nViews; ++fView) {
129 
130  const std::vector<size_t>& ClsIndices = ClsIndex[fView];
131 
132  for (size_t c = 0; c < ClsIndices.size(); ++c) {
133 
134  // find the hits associated with the current cluster
135  const std::vector<art::Ptr<recob::Hit>>& ptrvs = fm.at(ClsIndices[c]);
136 
137  double PrincDir[2], PrincValue = 0;
138  double TotalCharge = 0;
139 
140  PerformClusterPCA(ptrvs, PrincDir, PrincValue, TotalCharge, fNormPC);
141 
142  fPrincDirW = PrincDir[0];
143  fPrincDirT = PrincDir[1];
144  fPrincValue = PrincValue;
145  fTotalCharge = TotalCharge;
146  fNHits = ptrvs.size();
147 
148  fTree->Fill();
149 
150  } // end loop over first cluster iterator
151  } // end loop over planes
152 
153  return;
154 
155  } // ClusterPCA::analyze()
156 
157  // Perform PCA analysis of the hits in a cluster.
158  //
159  // This method is supplied with the vector of ptrs to hits in the cluster.
160  //
161  // It returns 2 things:
162  // 1. the principal direction, in [w,t] coordinates.
163  // 2. the principal eigenvalue, which is a measure of colinearity
164  //
165  // There is also a flag which can be specified to determine whether to normalize the PCA.
166  // For NormPC=true direction finding is not properly handled yet (easy to fix later)
167  // It is not clear yet whether true or false is more effective for cluster showeriness studies.
168 
170  double* PrincipalDirection,
171  double& PrincipalEigenvalue,
172  double& TotalCharge,
173  bool NormPC)
174  {
175 
176  double Center[2] = {0, 0};
177  TotalCharge = 0;
178 
179  for (auto itHit = HitsThisCluster.begin(); itHit != HitsThisCluster.end(); ++itHit) {
180  Center[0] += (*itHit)->WireID().Wire;
181  Center[1] += (*itHit)->PeakTime();
182  TotalCharge += (*itHit)->Integral();
183  }
184 
185  Center[0] /= float(HitsThisCluster.size());
186  Center[1] /= float(HitsThisCluster.size());
187 
188  double WireTime[2];
189 
190  std::string OptionString;
191 
192  if (NormPC == false)
193  OptionString = "D";
194  else
195  OptionString = "ND";
196 
197  TPrincipal pc(2, OptionString.c_str());
198 
199  for (auto itHit = HitsThisCluster.begin(); itHit != HitsThisCluster.end(); ++itHit) {
200  WireTime[0] = (*itHit)->WireID().Wire - Center[0];
201  WireTime[1] = (*itHit)->PeakTime() - Center[1];
202 
203  pc.AddRow(WireTime);
204  }
205 
206  pc.MakePrincipals();
207 
208  PrincipalEigenvalue = (*pc.GetEigenValues())[0];
209 
210  for (size_t n = 0; n != 2; ++n) {
211  PrincipalDirection[n] = (*pc.GetEigenVectors())[0][n];
212  }
213 
214  // Comment this out if you want to shut it up
215  pc.Print("MSEV");
216 
217  pc.Clear();
218  return;
219  }
220 
221 } // end namespace
222 
223 namespace cluster {
224 
226 
227 } // end namespace
Planes which measure V.
Definition: geo_types.h:136
Declaration of signal hit object.
STL namespace.
Planes which measure Z direction.
Definition: geo_types.h:138
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
Cluster finding and building.
EDAnalyzer(fhicl::ParameterSet const &pset)
Definition: EDAnalyzer.cc:6
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:289
Planes which measure U.
Definition: geo_types.h:135
void analyze(art::Event const &evt)
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:65
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)
geo::View_t View() const
Returns the view for this cluster.
Definition: Cluster.h:714
decltype(auto) get(T &&obj)
ADL-aware version of std::to_string.
Definition: StdUtils.h:120
ClusterPCA(fhicl::ParameterSet const &pset)
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
Char_t n[5]
TCEvent evt
Definition: DataStructs.cxx:8