File indexing completed on 2026-09-17 08:31:46
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 #include "ClusteringAlgo.hh"
0040
0041 #include "ClusteringAlgoMessenger.hh"
0042
0043 #include "G4SystemOfUnits.hh"
0044 #include "Randomize.hh"
0045
0046 #include <map>
0047
0048 using namespace std;
0049
0050
0051
0052 ClusteringAlgo::ClusteringAlgo(G4double pEps, G4int pMinPts, G4double pSPointsProb,
0053 G4double pEMinDamage, G4double pEMaxDamage)
0054 : fEps(pEps),
0055 fMinPts(pMinPts),
0056 fSPointsProb(pSPointsProb),
0057 fEMinDamage(pEMinDamage),
0058 fEMaxDamage(pEMaxDamage)
0059 {
0060 fNextSBPointID = 0;
0061 fpClustAlgoMessenger = new ClusteringAlgoMessenger(this);
0062 }
0063
0064
0065
0066 ClusteringAlgo::~ClusteringAlgo()
0067 {
0068 delete fpClustAlgoMessenger;
0069 Purge();
0070 }
0071
0072
0073
0074
0075 G4bool ClusteringAlgo::IsInSensitiveArea()
0076 {
0077 return fSPointsProb > G4UniformRand();
0078 }
0079
0080
0081
0082
0083 G4bool ClusteringAlgo::IsEdepSufficient(G4double pEdep)
0084 {
0085 if (pEdep < fEMinDamage) {
0086 return false;
0087 }
0088
0089 else if (pEdep > fEMaxDamage) {
0090 return true;
0091 }
0092 else {
0093 G4double proba = (pEdep / eV - fEMinDamage / eV) / (fEMaxDamage / eV - fEMinDamage / eV);
0094 return (proba > G4UniformRand());
0095 }
0096 }
0097
0098
0099
0100
0101
0102
0103
0104 void ClusteringAlgo::RegisterDamage(G4ThreeVector pPos, G4double pEdep)
0105 {
0106 if (IsEdepSufficient(pEdep)) {
0107 if (IsInSensitiveArea()) {
0108 fpSetOfPoints.push_back(new SBPoint(fNextSBPointID++, pPos, pEdep));
0109 }
0110 }
0111 }
0112
0113
0114
0115 map<G4int, G4int> ClusteringAlgo::RunClustering()
0116 {
0117
0118
0119 std::vector<SBPoint*>::iterator itVisitorPt, itObservedPt;
0120 for (itVisitorPt = fpSetOfPoints.begin(); itVisitorPt != fpSetOfPoints.end(); ++itVisitorPt) {
0121 itObservedPt = itVisitorPt;
0122 itObservedPt++;
0123 while (itObservedPt != fpSetOfPoints.end()) {
0124
0125 if (!((*itObservedPt)->HasCluster() && (*itVisitorPt)->HasCluster())) {
0126 if (AreOnTheSameCluster((*itObservedPt)->GetPosition(), (*itVisitorPt)->GetPosition(),
0127 fEps))
0128 {
0129
0130 if (!(*itObservedPt)->HasCluster() && !(*itVisitorPt)->HasCluster()) {
0131
0132 set<SBPoint*> clusterPoints;
0133 clusterPoints.insert((*itObservedPt));
0134 clusterPoints.insert((*itVisitorPt));
0135 ClusterSBPoints* lCluster = new ClusterSBPoints(clusterPoints);
0136 assert(lCluster);
0137 fpClusters.push_back(lCluster);
0138 assert(lCluster);
0139
0140 assert(lCluster);
0141 (*itObservedPt)->SetCluster(lCluster);
0142 assert(lCluster);
0143 (*itVisitorPt)->SetCluster(lCluster);
0144 }
0145 else {
0146
0147 if ((*itObservedPt)->HasCluster()) {
0148 (*itObservedPt)->GetCluster()->AddSBPoint((*itVisitorPt));
0149 (*itVisitorPt)->SetCluster((*itObservedPt)->GetCluster());
0150 }
0151
0152 if ((*itVisitorPt)->HasCluster()) {
0153 (*itVisitorPt)->GetCluster()->AddSBPoint((*itObservedPt));
0154 (*itObservedPt)->SetCluster((*itVisitorPt)->GetCluster());
0155 }
0156 }
0157 }
0158 }
0159 ++itObservedPt;
0160 }
0161 }
0162
0163
0164 IncludeUnassociatedPoints();
0165 MergeClusters();
0166
0167
0168 return GetClusterSizeDistribution();
0169 }
0170
0171
0172
0173
0174 void ClusteringAlgo::MergeClusters()
0175 {
0176 std::vector<ClusterSBPoints*>::iterator itCluster1, itCluster2;
0177 for (itCluster1 = fpClusters.begin(); itCluster1 != fpClusters.end(); ++itCluster1) {
0178 G4ThreeVector baryCenterClust1 = (*itCluster1)->GetBarycenter();
0179 itCluster2 = itCluster1;
0180 itCluster2++;
0181 while (itCluster2 != fpClusters.end()) {
0182 G4ThreeVector baryCenterClust2 = (*itCluster2)->GetBarycenter();
0183
0184 if (AreOnTheSameCluster(baryCenterClust1, baryCenterClust2, fEps)) {
0185 (*itCluster1)->MergeWith(*itCluster2);
0186 delete *itCluster2;
0187 fpClusters.erase(itCluster2);
0188 return MergeClusters();
0189 }
0190 else {
0191 itCluster2++;
0192 }
0193 }
0194 }
0195 }
0196
0197
0198
0199 void ClusteringAlgo::IncludeUnassociatedPoints()
0200 {
0201 std::vector<SBPoint*>::iterator itVisitorPt;
0202
0203 for (itVisitorPt = fpSetOfPoints.begin(); itVisitorPt != fpSetOfPoints.end(); ++itVisitorPt) {
0204 if (!(*itVisitorPt)->HasCluster()) {
0205 FindCluster(*itVisitorPt);
0206 }
0207 }
0208 }
0209
0210
0211
0212 bool ClusteringAlgo::FindCluster(SBPoint* pPt)
0213 {
0214 assert(!pPt->HasCluster());
0215 std::vector<ClusterSBPoints*>::iterator itCluster;
0216 for (itCluster = fpClusters.begin(); itCluster != fpClusters.end(); ++itCluster) {
0217
0218 if ((*itCluster)->HasInBarycenter(pPt, fEps)) {
0219 (*itCluster)->AddSBPoint(pPt);
0220 return true;
0221 }
0222 }
0223 return false;
0224 }
0225
0226
0227
0228 bool ClusteringAlgo::AreOnTheSameCluster(G4ThreeVector pPt1, G4ThreeVector pPt2, G4double pMinDist)
0229 {
0230 G4double x1 = pPt1.x() / nm;
0231 G4double y1 = pPt1.y() / nm;
0232 G4double z1 = pPt1.z() / nm;
0233
0234 G4double x2 = pPt2.x() / nm;
0235 G4double y2 = pPt2.y() / nm;
0236 G4double z2 = pPt2.z() / nm;
0237
0238
0239 if (((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2))
0240 <= (pMinDist / nm * pMinDist / nm))
0241 {
0242 return true;
0243 }
0244 else {
0245 return false;
0246 }
0247 }
0248
0249
0250
0251 G4int ClusteringAlgo::GetSSB() const
0252 {
0253 G4int nbSSB = 0;
0254 std::vector<SBPoint*>::const_iterator itSDSPt;
0255 for (itSDSPt = fpSetOfPoints.begin(); itSDSPt != fpSetOfPoints.end(); ++itSDSPt) {
0256 if (!(*itSDSPt)->HasCluster()) {
0257 nbSSB++;
0258 }
0259 }
0260 return nbSSB;
0261 }
0262
0263
0264
0265 G4int ClusteringAlgo::GetComplexSSB() const
0266 {
0267 G4int nbSSB = 0;
0268 std::vector<ClusterSBPoints*>::const_iterator itCluster;
0269 for (itCluster = fpClusters.begin(); itCluster != fpClusters.end(); ++itCluster) {
0270 if ((*itCluster)->IsSSB()) {
0271 nbSSB++;
0272 }
0273 }
0274 return nbSSB;
0275 }
0276
0277
0278
0279 G4int ClusteringAlgo::GetDSB() const
0280 {
0281 G4int nbDSB = 0;
0282 std::vector<ClusterSBPoints*>::const_iterator itCluster;
0283 for (itCluster = fpClusters.begin(); itCluster != fpClusters.end(); ++itCluster) {
0284 if ((*itCluster)->IsDSB()) {
0285 nbDSB++;
0286 }
0287 }
0288 return nbDSB;
0289 }
0290
0291
0292
0293 map<G4int, G4int> ClusteringAlgo::GetClusterSizeDistribution()
0294 {
0295 std::map<G4int, G4int> sizeDistribution;
0296 sizeDistribution[1] = GetSSB();
0297 std::vector<ClusterSBPoints*>::const_iterator itCluster;
0298 for (itCluster = fpClusters.begin(); itCluster != fpClusters.end(); itCluster++) {
0299 sizeDistribution[(*itCluster)->GetSize()]++;
0300 }
0301 return sizeDistribution;
0302 }
0303
0304
0305
0306 void ClusteringAlgo::Purge()
0307 {
0308 fNextSBPointID = 0;
0309 std::vector<ClusterSBPoints*>::iterator itCluster;
0310 for (itCluster = fpClusters.begin(); itCluster != fpClusters.end(); ++itCluster) {
0311 delete *itCluster;
0312 *itCluster = NULL;
0313 }
0314 fpClusters.clear();
0315 std::vector<SBPoint*>::iterator itPt;
0316 for (itPt = fpSetOfPoints.begin(); itPt != fpSetOfPoints.end(); ++itPt) {
0317 delete *itPt;
0318 *itPt = NULL;
0319 }
0320 fpSetOfPoints.clear();
0321 }