All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Public Member Functions | Private Member Functions | Private Attributes | List of all members
lar_content::LongitudinalExtensionAlgorithm Class Reference

LongitudinalExtensionAlgorithm class. More...

#include <LongitudinalExtensionAlgorithm.h>

Inheritance diagram for lar_content::LongitudinalExtensionAlgorithm:
lar_content::ClusterExtensionAlgorithm lar_content::ClusterMergingAlgorithm

Public Member Functions

 LongitudinalExtensionAlgorithm ()
 Default constructor. More...
 

Private Member Functions

void GetListOfCleanClusters (const pandora::ClusterList *const pClusterList, pandora::ClusterVector &clusterVector) const
 Populate cluster vector with subset of cluster list, containing clusters judged to be clean. More...
 
void FillClusterAssociationMatrix (const pandora::ClusterVector &clusterVector, ClusterAssociationMatrix &clusterAssociationMatrix) const
 Fill the cluster association matrix. More...
 
void FillClusterMergeMap (const ClusterAssociationMatrix &clusterAssociationMatrix, ClusterMergeMap &clusterMergeMap) const
 Fill the cluster merge map. More...
 
void FillClusterAssociationMatrix (const LArPointingCluster &clusterI, const LArPointingCluster &clusterJ, ClusterAssociationMatrix &clusterAssociationMatrix) const
 Form association between two pointing clusters. More...
 
pandora::StatusCode ReadSettings (const pandora::TiXmlHandle xmlHandle)
 

Private Attributes

float m_clusterMinLength
 
float m_clusterMinLayerOccupancy
 
float m_nodeMaxDisplacement
 
float m_nodeMaxCosRelativeAngle
 
float m_emissionMaxLongitudinalDisplacement
 
float m_emissionMaxTransverseDisplacement
 
float m_emissionMaxCosRelativeAngle
 

Additional Inherited Members

- Protected Types inherited from lar_content::ClusterExtensionAlgorithm
typedef std::unordered_map
< const pandora::Cluster
*, ClusterAssociation
ClusterAssociationMap
 
typedef std::unordered_map
< const pandora::Cluster
*, ClusterAssociationMap
ClusterAssociationMatrix
 
- Protected Types inherited from lar_content::ClusterMergingAlgorithm
typedef std::unordered_map
< const pandora::Cluster
*, pandora::ClusterList > 
ClusterMergeMap
 
- Protected Member Functions inherited from lar_content::ClusterExtensionAlgorithm
void PopulateClusterMergeMap (const pandora::ClusterVector &clusterVector, ClusterMergeMap &clusterMergeMatrix) const
 Form associations between pointing clusters. More...
 
- Protected Member Functions inherited from lar_content::ClusterMergingAlgorithm
virtual pandora::StatusCode Run ()
 
void MergeClusters (pandora::ClusterVector &clusterVector, ClusterMergeMap &clusterMergeMap) const
 Merge associated clusters. More...
 
void CollectAssociatedClusters (const pandora::Cluster *const pSeedCluster, const ClusterMergeMap &clusterMergeMap, pandora::ClusterList &associatedClusterList) const
 Collect up all clusters associations related to a given seed cluster. More...
 
void CollectAssociatedClusters (const pandora::Cluster *const pSeedCluster, const pandora::Cluster *const pCurrentCluster, const ClusterMergeMap &clusterMergeMap, const pandora::ClusterSet &clusterVetoList, pandora::ClusterList &associatedClusterList) const
 Collect up all clusters associations related to a given seed cluster. More...
 
void GetSortedListOfCleanClusters (const pandora::ClusterVector &inputClusters, pandora::ClusterVector &outputClusters) const
 Sort the selected clusters, so that they have a well-defined ordering. More...
 
- Protected Attributes inherited from lar_content::ClusterMergingAlgorithm
std::string m_inputClusterListName
 The name of the input cluster list. If not specified, will access current list. More...
 

Detailed Description

LongitudinalExtensionAlgorithm class.

Definition at line 21 of file LongitudinalExtensionAlgorithm.h.

Constructor & Destructor Documentation

lar_content::LongitudinalExtensionAlgorithm::LongitudinalExtensionAlgorithm ( )

Member Function Documentation

void lar_content::LongitudinalExtensionAlgorithm::FillClusterAssociationMatrix ( const pandora::ClusterVector &  clusterVector,
ClusterAssociationMatrix clusterAssociationMatrix 
) const
privatevirtual

Fill the cluster association matrix.

Parameters
clusterVectorthe input vector of clusters
clusterAssociationMatrixthe matrix of associations

Implements lar_content::ClusterExtensionAlgorithm.

void lar_content::LongitudinalExtensionAlgorithm::FillClusterAssociationMatrix ( const LArPointingCluster clusterI,
const LArPointingCluster clusterJ,
ClusterAssociationMatrix clusterAssociationMatrix 
) const
private

Form association between two pointing clusters.

Parameters
clusterIthe first pointing cluster
clusterJthe second pointing cluster
clusterAssociationMatrixthe matrix of cluster associations

Definition at line 89 of file LongitudinalExtensionAlgorithm.cc.

91 {
92  const Cluster *const pClusterI(clusterI.GetCluster());
93  const Cluster *const pClusterJ(clusterJ.GetCluster());
94 
95  if (pClusterI == pClusterJ)
96  return;
97 
98  // Check that new layer occupancy would be reasonable
100  return;
101 
102  // Identify closest pair of vertices
103  LArPointingCluster::Vertex targetVertexI, targetVertexJ;
104 
105  try
106  {
107  LArPointingClusterHelper::GetClosestVertices(clusterI, clusterJ, targetVertexI, targetVertexJ);
108  }
109  catch (StatusCodeException &)
110  {
111  return;
112  }
113 
114  // (Just in case...)
115  if (!(targetVertexI.IsInitialized() && targetVertexJ.IsInitialized()))
116  throw StatusCodeException(STATUS_CODE_FAILURE);
117 
118  const CartesianVector &vertexPositionI(targetVertexI.GetPosition());
119  const CartesianVector &vertexPositionJ(targetVertexJ.GetPosition());
120  const CartesianVector &vertexDirectionI(targetVertexI.GetDirection());
121  const CartesianVector &vertexDirectionJ(targetVertexJ.GetDirection());
122 
123  // Check for reasonable proximity between vertices
124  const float distanceSquared((vertexPositionI - vertexPositionJ).GetMagnitudeSquared());
125 
127  return;
128 
129  // Check that vertices have a reasonable linear fit
130  if (targetVertexI.GetRms() > 1.f || targetVertexJ.GetRms() > 1.f)
131  return;
132 
133  // Association type
135 
136  // Requirements for Nodes
137  if (distanceSquared < 2.f * m_nodeMaxDisplacement * m_nodeMaxDisplacement)
138  {
139  associationType = ClusterAssociation::WEAK;
140 
141  if (distanceSquared < m_nodeMaxDisplacement * m_nodeMaxDisplacement)
142  {
143  const float cosTheta(-vertexDirectionI.GetDotProduct(vertexDirectionJ));
144 
145  if (cosTheta > m_nodeMaxCosRelativeAngle)
146  {
147  associationType = ClusterAssociation::STRONG;
148  }
149  }
150  }
151 
152  // Requirements for Emissions
153  const float clusterLengthI(LArPointingClusterHelper::GetLength(clusterI));
154  const float clusterLengthJ(LArPointingClusterHelper::GetLength(clusterJ));
155 
156  if (associationType < ClusterAssociation::STRONG)
157  {
158  const float cosTheta(-vertexDirectionI.GetDotProduct(vertexDirectionJ));
159  const float cosThetaI((vertexPositionI - vertexPositionJ).GetUnitVector().GetDotProduct(vertexDirectionI));
160  const float cosThetaJ((vertexPositionJ - vertexPositionI).GetUnitVector().GetDotProduct(vertexDirectionJ));
161 
162  float rT1(0.f), rL1(0.f), rT2(0.f), rL2(0.f);
163  LArPointingClusterHelper::GetImpactParameters(vertexPositionI, vertexDirectionI, vertexPositionJ, rL1, rT1);
164  LArPointingClusterHelper::GetImpactParameters(vertexPositionJ, vertexDirectionJ, vertexPositionI, rL2, rT2);
165 
166  if ((rL1 > -2.5f && rL1 < std::min(0.66f * clusterLengthJ, m_emissionMaxLongitudinalDisplacement)) &&
167  (rL2 > -2.5f && rL2 < std::min(0.66f * clusterLengthI, m_emissionMaxLongitudinalDisplacement)) && (rT1 < m_emissionMaxTransverseDisplacement) &&
168  (rT2 < m_emissionMaxTransverseDisplacement) && (targetVertexI.GetRms() < 0.5f && targetVertexJ.GetRms() < 0.5f) &&
169  (cosTheta > m_emissionMaxCosRelativeAngle) && (std::fabs(cosThetaI) > 0.25f) && (std::fabs(cosThetaJ) > 0.25f))
170  {
171  associationType = ClusterAssociation::STRONG;
172  }
173  }
174 
175  // Record the association
176  if (ClusterAssociation::NONE != associationType)
177  {
178  const ClusterAssociation::VertexType vertexTypeI(targetVertexI.IsInnerVertex() ? ClusterAssociation::INNER : ClusterAssociation::OUTER);
179  const ClusterAssociation::VertexType vertexTypeJ(targetVertexJ.IsInnerVertex() ? ClusterAssociation::INNER : ClusterAssociation::OUTER);
180  (void)clusterAssociationMatrix[pClusterI].insert(
181  ClusterAssociationMap::value_type(pClusterJ, ClusterAssociation(vertexTypeI, vertexTypeJ, associationType, clusterLengthJ)));
182  (void)clusterAssociationMatrix[pClusterJ].insert(
183  ClusterAssociationMap::value_type(pClusterI, ClusterAssociation(vertexTypeJ, vertexTypeI, associationType, clusterLengthI)));
184  return;
185  }
186 }
static void GetImpactParameters(const LArPointingCluster::Vertex &pointingVertex, const LArPointingCluster::Vertex &targetVertex, float &longitudinal, float &transverse)
Calculate impact parameters between a pair of pointing vertices.
static float GetLength(const LArPointingCluster &pointingCluster)
Calculate distance squared between inner and outer vertices of pointing cluster.
static void GetClosestVertices(const bool useX, const bool useY, const bool useZ, const LArPointingCluster &pointingClusterI, const LArPointingCluster &pointingClusterJ, LArPointingCluster::Vertex &closestVertexI, LArPointingCluster::Vertex &closestVertexJ)
Given a pair of pointing clusters, receive the closest or farthest pair of vertices.
j template void())
Definition: json.hpp:3108
static float GetLayerOccupancy(const pandora::Cluster *const pCluster)
Fraction of occupied layers in cluster.
void lar_content::LongitudinalExtensionAlgorithm::FillClusterMergeMap ( const ClusterAssociationMatrix clusterAssociationMatrix,
ClusterMergeMap clusterMergeMap 
) const
privatevirtual

Fill the cluster merge map.

Parameters
clusterAssociationMatrixthe matrix of cluster associations
clusterMergeMapthe map of cluster merges

Implements lar_content::ClusterExtensionAlgorithm.

Definition at line 190 of file LongitudinalExtensionAlgorithm.cc.

191 {
192  // Decide which associations will become merges
193  // To make the merge A <-> B, both A -> B and B -> A must be strong associations
194  // with the largest figures of merit of all the A -> X and B -> Y associations
195 
196  // First step: remove double-counting from the map of associations
197  // i.e. if the map has A <-> B, B <-> C, A <-> C, then remove A <-> C
198  ClusterAssociationMatrix clusterAssociationMatrix;
199 
200  ClusterVector sortedInputClusters;
201  for (const auto &mapEntry : inputAssociationMatrix)
202  sortedInputClusters.push_back(mapEntry.first);
203  std::sort(sortedInputClusters.begin(), sortedInputClusters.end(), LArClusterHelper::SortByNHits);
204 
205  for (const Cluster *const pCluster1 : sortedInputClusters)
206  {
207  const ClusterAssociationMap &associationMap1(inputAssociationMatrix.at(pCluster1));
208 
209  for (const Cluster *const pCluster2 : sortedInputClusters)
210  {
211  if (pCluster1 == pCluster2)
212  continue;
213 
214  const ClusterAssociationMap &associationMap2(inputAssociationMatrix.at(pCluster2));
215 
216  ClusterAssociationMap::const_iterator iter12 = associationMap1.find(pCluster2);
217  if (associationMap1.end() == iter12)
218  continue;
219 
220  ClusterAssociationMap::const_iterator iter21 = associationMap2.find(pCluster1);
221  if (associationMap2.end() == iter21)
222  continue;
223 
224  const ClusterAssociation &association12(iter12->second);
225  const ClusterAssociation &association21(iter21->second);
226 
227  bool isAssociated(true);
228 
229  ClusterVector sortedAssociationClusters;
230  for (const auto &mapEntry : associationMap1)
231  sortedAssociationClusters.push_back(mapEntry.first);
232  std::sort(sortedAssociationClusters.begin(), sortedAssociationClusters.end(), LArClusterHelper::SortByNHits);
233 
234  for (const Cluster *const pCluster3 : sortedAssociationClusters)
235  {
236  const ClusterAssociation &association13(associationMap1.at(pCluster3));
237 
238  ClusterAssociationMap::const_iterator iter23 = associationMap2.find(pCluster3);
239  if (associationMap2.end() == iter23)
240  continue;
241 
242  const ClusterAssociation &association23(iter23->second);
243 
244  if (association12.GetParent() == association13.GetParent() && association23.GetParent() == association21.GetParent() &&
245  association13.GetDaughter() != association23.GetDaughter())
246  {
247  isAssociated = false;
248  break;
249  }
250  }
251 
252  if (isAssociated)
253  {
254  (void)clusterAssociationMatrix[pCluster1].insert(ClusterAssociationMap::value_type(pCluster2, association12));
255  (void)clusterAssociationMatrix[pCluster2].insert(ClusterAssociationMap::value_type(pCluster1, association21));
256  }
257  }
258  }
259 
260  // Second step: find the best associations A -> X and B -> Y
261  ClusterAssociationMatrix intermediateAssociationMatrix;
262 
263  ClusterVector sortedClusters;
264  for (const auto &mapEntry : clusterAssociationMatrix)
265  sortedClusters.push_back(mapEntry.first);
266  std::sort(sortedClusters.begin(), sortedClusters.end(), LArClusterHelper::SortByNHits);
267 
268  for (const Cluster *const pParentCluster : sortedClusters)
269  {
270  const ClusterAssociationMap &clusterAssociationMap(clusterAssociationMatrix.at(pParentCluster));
271 
272  const Cluster *pBestClusterInner(nullptr);
273  ClusterAssociation bestAssociationInner(ClusterAssociation::UNDEFINED, ClusterAssociation::UNDEFINED, ClusterAssociation::NONE, 0.f);
274 
275  const Cluster *pBestClusterOuter(nullptr);
276  ClusterAssociation bestAssociationOuter(ClusterAssociation::UNDEFINED, ClusterAssociation::UNDEFINED, ClusterAssociation::NONE, 0.f);
277 
278  ClusterVector sortedAssociationClusters;
279  for (const auto &mapEntry : clusterAssociationMap)
280  sortedAssociationClusters.push_back(mapEntry.first);
281  std::sort(sortedAssociationClusters.begin(), sortedAssociationClusters.end(), LArClusterHelper::SortByNHits);
282 
283  for (const Cluster *const pDaughterCluster : sortedAssociationClusters)
284  {
285  const ClusterAssociation &clusterAssociation(clusterAssociationMap.at(pDaughterCluster));
286 
287  // Inner associations
288  if (clusterAssociation.GetParent() == ClusterAssociation::INNER)
289  {
290  if (clusterAssociation.GetFigureOfMerit() > bestAssociationInner.GetFigureOfMerit())
291  {
292  bestAssociationInner = clusterAssociation;
293 
294  if (clusterAssociation.GetAssociation() == ClusterAssociation::STRONG)
295  pBestClusterInner = pDaughterCluster;
296  else
297  pBestClusterInner = nullptr;
298  }
299  }
300 
301  // Outer associations
302  if (clusterAssociation.GetParent() == ClusterAssociation::OUTER)
303  {
304  if (clusterAssociation.GetFigureOfMerit() > bestAssociationOuter.GetFigureOfMerit())
305  {
306  bestAssociationOuter = clusterAssociation;
307 
308  if (clusterAssociation.GetAssociation() == ClusterAssociation::STRONG)
309  pBestClusterOuter = pDaughterCluster;
310  else
311  pBestClusterOuter = nullptr;
312  }
313  }
314  }
315 
316  if (pBestClusterInner)
317  (void)intermediateAssociationMatrix[pParentCluster].insert(ClusterAssociationMap::value_type(pBestClusterInner, bestAssociationInner));
318 
319  if (pBestClusterOuter)
320  (void)intermediateAssociationMatrix[pParentCluster].insert(ClusterAssociationMap::value_type(pBestClusterOuter, bestAssociationOuter));
321  }
322 
323  // Third step: make the merge if A -> X and B -> Y is in fact A -> B and B -> A
324  ClusterVector intermediateSortedClusters;
325  for (const auto &mapEntry : intermediateAssociationMatrix)
326  intermediateSortedClusters.push_back(mapEntry.first);
327  std::sort(intermediateSortedClusters.begin(), intermediateSortedClusters.end(), LArClusterHelper::SortByNHits);
328 
329  for (const Cluster *const pParentCluster : intermediateSortedClusters)
330  {
331  const ClusterAssociationMap &parentAssociationMap(intermediateAssociationMatrix.at(pParentCluster));
332 
333  ClusterVector sortedAssociationClusters;
334  for (const auto &mapEntry : parentAssociationMap)
335  sortedAssociationClusters.push_back(mapEntry.first);
336  std::sort(sortedAssociationClusters.begin(), sortedAssociationClusters.end(), LArClusterHelper::SortByNHits);
337 
338  for (const Cluster *const pDaughterCluster : sortedAssociationClusters)
339  {
340  const ClusterAssociation &parentToDaughterAssociation(parentAssociationMap.at(pDaughterCluster));
341 
342  ClusterAssociationMatrix::const_iterator iter5 = intermediateAssociationMatrix.find(pDaughterCluster);
343 
344  if (intermediateAssociationMatrix.end() == iter5)
345  continue;
346 
347  const ClusterAssociationMap &daughterAssociationMap(iter5->second);
348 
349  ClusterAssociationMap::const_iterator iter6 = daughterAssociationMap.find(pParentCluster);
350 
351  if (daughterAssociationMap.end() == iter6)
352  continue;
353 
354  const ClusterAssociation &daughterToParentAssociation(iter6->second);
355 
356  if (parentToDaughterAssociation.GetParent() == daughterToParentAssociation.GetDaughter() &&
357  parentToDaughterAssociation.GetDaughter() == daughterToParentAssociation.GetParent())
358  {
359  ClusterList &parentList(clusterMergeMap[pParentCluster]);
360 
361  if (parentList.end() == std::find(parentList.begin(), parentList.end(), pDaughterCluster))
362  parentList.push_back(pDaughterCluster);
363  }
364  }
365  }
366 }
static bool SortByNHits(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by number of hits, then layer span, then inner layer, then position, then pulse-height.
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap
std::unordered_map< const pandora::Cluster *, ClusterAssociationMap > ClusterAssociationMatrix
j template void())
Definition: json.hpp:3108
std::vector< art::Ptr< recob::Cluster > > ClusterVector
void lar_content::LongitudinalExtensionAlgorithm::GetListOfCleanClusters ( const pandora::ClusterList *const  pClusterList,
pandora::ClusterVector &  clusterVector 
) const
privatevirtual

Populate cluster vector with subset of cluster list, containing clusters judged to be clean.

Parameters
pClusterListaddress of the cluster list
clusterVectorto receive the populated cluster vector

Implements lar_content::ClusterMergingAlgorithm.

Definition at line 34 of file LongitudinalExtensionAlgorithm.cc.

35 {
36  for (ClusterList::const_iterator iter = pClusterList->begin(), iterEnd = pClusterList->end(); iter != iterEnd; ++iter)
37  {
38  const Cluster *const pCluster = *iter;
39 
41  continue;
42 
44  continue;
45 
46  clusterVector.push_back(pCluster);
47  }
48 
49  std::sort(clusterVector.begin(), clusterVector.end(), LArClusterHelper::SortByNHits);
50 }
static bool SortByNHits(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by number of hits, then layer span, then inner layer, then position, then pulse-height.
static float GetLayerOccupancy(const pandora::Cluster *const pCluster)
Fraction of occupied layers in cluster.
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster.
StatusCode lar_content::LongitudinalExtensionAlgorithm::ReadSettings ( const pandora::TiXmlHandle  xmlHandle)
privatevirtual

Reimplemented from lar_content::ClusterMergingAlgorithm.

Definition at line 370 of file LongitudinalExtensionAlgorithm.cc.

371 {
372  PANDORA_RETURN_RESULT_IF_AND_IF(
373  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ClusterMinLength", m_clusterMinLength));
374 
375  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
376  XmlHelper::ReadValue(xmlHandle, "ClusterMinLayerOccupancy", m_clusterMinLayerOccupancy));
377 
378  PANDORA_RETURN_RESULT_IF_AND_IF(
379  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "NodeMaxDisplacement", m_nodeMaxDisplacement));
380 
381  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
382  XmlHelper::ReadValue(xmlHandle, "NodeMaxCosRelativeAngle", m_nodeMaxCosRelativeAngle));
383 
384  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
385  XmlHelper::ReadValue(xmlHandle, "EmissionMaxLongitudinalDisplacement", m_emissionMaxLongitudinalDisplacement));
386 
387  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
388  XmlHelper::ReadValue(xmlHandle, "EmissionMaxTransverseDisplacement", m_emissionMaxTransverseDisplacement));
389 
390  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
391  XmlHelper::ReadValue(xmlHandle, "EmissionMaxCosRelativeAngle", m_emissionMaxCosRelativeAngle));
392 
393  return ClusterExtensionAlgorithm::ReadSettings(xmlHandle);
394 }
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)

Member Data Documentation

float lar_content::LongitudinalExtensionAlgorithm::m_clusterMinLayerOccupancy
private

Definition at line 47 of file LongitudinalExtensionAlgorithm.h.

float lar_content::LongitudinalExtensionAlgorithm::m_clusterMinLength
private

Definition at line 46 of file LongitudinalExtensionAlgorithm.h.

float lar_content::LongitudinalExtensionAlgorithm::m_emissionMaxCosRelativeAngle
private

Definition at line 52 of file LongitudinalExtensionAlgorithm.h.

float lar_content::LongitudinalExtensionAlgorithm::m_emissionMaxLongitudinalDisplacement
private

Definition at line 50 of file LongitudinalExtensionAlgorithm.h.

float lar_content::LongitudinalExtensionAlgorithm::m_emissionMaxTransverseDisplacement
private

Definition at line 51 of file LongitudinalExtensionAlgorithm.h.

float lar_content::LongitudinalExtensionAlgorithm::m_nodeMaxCosRelativeAngle
private

Definition at line 49 of file LongitudinalExtensionAlgorithm.h.

float lar_content::LongitudinalExtensionAlgorithm::m_nodeMaxDisplacement
private

Definition at line 48 of file LongitudinalExtensionAlgorithm.h.


The documentation for this class was generated from the following files: