51 #include "StFmsDbMaker/StFmsDbMaker.h"
52 #include "StFmsDbConfig.h"
59 #include "TObjArray.h"
61 #include "St_base/StMessMgr.h"
62 #include "StEvent/StFmsCluster.h"
63 #include "StEvent/StFmsHit.h"
66 #include "StFmsUtil/StFmsConstant.h"
70 typedef FMSCluster::StFmsClusterFinder::TowerList TowerList;
71 typedef TowerList::const_reverse_iterator TowerConstRIter;
81 bool couldBePeakTower(
const StFmsTower* tower,
const StFmsTower* other) {
82 return (tower->hit()->energy() >= PEAK_TOWER_FACTOR * other->hit()->energy()) ?
true :
false;
91 bool couldBePeakTower(
const StFmsTower* tower, TowerList* others) {
92 for (
auto i = others->begin(); i != others->end(); ++i) {
93 if (tower->isNeighbor(**i) && !couldBePeakTower(tower, *i)) {
101 bool ascendingTowerEnergySorter(
const StFmsTower* a,
const StFmsTower* b) {
102 return a->
hit()->energy() < b->hit()->energy();
106 bool descendingTowerEnergySorter(
const StFmsTower* a,
const StFmsTower* b) {
107 return a->hit()->energy() > b->hit()->energy();
111 bool towerEnergyIsAboveThreshold(
const StFmsTower* tower) {
112 return !(tower->hit()->energy() < TOWER_E_THRESHOLD);
123 bool towerIsNeighbor(
const StFmsTower* test,
const StFmsTower* reference) {
124 if (towerEnergyIsAboveThreshold(test)) {
125 return test->isNeighbor(*reference);
136 TowerList filterTowersBelowEnergyThreshold(TowerList* towers) {
140 auto newEnd = std::partition(towers->begin(), towers->end(),
141 std::ptr_fun(&towerEnergyIsAboveThreshold));
143 TowerList belowThreshold(newEnd, towers->end());
145 towers->erase(newEnd, towers->end());
146 return belowThreshold;
150 enum ETowerClusterDistance {
156 void sortTowersEnergyDescending(FMSCluster::ClusterList* clusters) {
157 for (
auto i = clusters->begin(); i != clusters->end(); ++i) {
158 (*i)->towers().sort(std::ptr_fun(&descendingTowerEnergySorter));
163 namespace FMSCluster {
188 std::list<StFmsTowerCluster*>*
clusters() {
return &mClusters; }
197 int det0=mTower->
hit()->detectorId();
198 int det1=tower->
hit()->detectorId();
201 return sqrt(pow(tower->
column() - mTower->
column(), 2.) +
202 pow(tower->
row() - mTower->
row(), 2.));
205 int rowL,colL,rowS,colS;
207 rowL=mTower->
row(); rowS=tower->
row();
210 rowS=mTower->
row(); rowL=tower->
row();
215 float rS=(rowS-0.5)/1.5 + 9.0;
216 float cS=(colS-0.5)/1.5;
217 return sqrt(pow(rL-rS,2.0)+pow(cL-cS,2.0));
230 const ETowerClusterDistance distance) {
231 if (kPeakTower == distance) {
236 if(mTower->
hit()->detectorId() == mDetectorId){
237 return sqrt(pow(cluster->
cluster()->x() - (mTower->
column() - 0.5), 2.) +
238 pow(cluster->
cluster()->y() - (mTower->
row() - 0.5), 2.));
240 float col=(mTower->
column()-0.5)/1.5;
241 float row=(mTower->
row()-0.5)/1.5+9.0;
242 return sqrt(pow(cluster->
cluster()->x() - col,2.0) +
243 pow(cluster->
cluster()->y() - row,2.0));
267 if (peak->
hit()->energy() < mTower->
hit()->energy()) {
272 for (
auto tower = towers.begin(); tower != towers.end(); ++
tower) {
273 if (mTower->
isNeighbor(**tower) && !couldBePeakTower(mTower, *tower)) {
300 if (mClusters.empty()) {
305 double distNew =
separation(cluster, distance);
306 double distOld =
separation(mClusters.front(), distance);
307 if (distNew < distOld) {
311 if (!(distNew > distOld)) {
319 mClusters.push_back(cluster);
333 double minDist = 99999.;
334 for (
auto i = mClusters.begin(); i != mClusters.end(); ++i) {
335 double distance =
separation(*i, kClusterCenter);
337 if (distance < minDist) {
348 std::list<StFmsTowerCluster*> mClusters;
352 : mEnergyCutoff(energyCutoff), mNClusts(0), mDetectorId(0) { }
364 if (cluster->nTowers() < CAT_NTOWERS_PH1) {
367 const double sigmaMaxE = cluster->sigmaMax() * cluster->energy();
368 if (cluster->energy() < CAT_EP1_PH2 * (sigmaMaxE - CAT_EP0_PH2)) {
369 if (sigmaMaxE > CAT_SIGMAMAX_MIN_PH2) {
374 }
else if (cluster->energy() > CAT_EP1_PH1 * (sigmaMaxE - CAT_EP0_PH1)) {
375 if (sigmaMaxE < CAT_SIGMAMAX_MAX_PH1) {
384 return cluster->category();
389 if (cluster->nTowers() < CAT_NTOWERS_PH1) {
393 const double sigma=cluster->sigmaMax();
394 const double e =cluster->energy();
395 if(sigma > 1/2.5 + 0.003*e + 7.0/e){
397 }
else if(sigma < 1/2.1 -0.001*e + 2.0/e){
404 return cluster->category();
408 mDetectorId=detectorId;
410 TowerList belowThreshold = filterTowersBelowEnergyThreshold(towers);
412 locateClusterSeeds(towers, &neighbors, clusters);
415 neighbors.sort(std::ptr_fun(&ascendingTowerEnergySorter));
421 TObjArray valleys(16);
422 valleys.SetOwner(
true);
423 unsigned nAssociations(0);
425 nAssociations = associateTowersWithClusters(&neighbors, clusters, &valleys);
426 }
while (nAssociations > 0);
430 for (
auto i = clusters->begin(); i != clusters->end(); ++i) {
435 associateValleyTowersWithClusters(&neighbors, clusters, &valleys);
438 nAssociations = associateResidualTowersWithClusters(&neighbors, clusters);
439 }
while (nAssociations > 0);
441 sortTowersEnergyDescending(clusters);
443 for (
auto i = clusters->begin(); i != clusters->end(); ++i) {
447 associateSubThresholdTowersWithClusters(&belowThreshold, clusters);
451 unsigned StFmsClusterFinder::locateClusterSeeds(TowerList* towers,
452 TowerList* neighbors,
453 ClusterList* clusters)
const {
455 towers->sort(std::ptr_fun(&descendingTowerEnergySorter));
456 while (!towers->empty() && clusters->size() < kMaxNClusters) {
464 if (couldBePeakTower(high, neighbors)) {
467 typedef FMSCluster::ClusterList::value_type ClusterPtr;
469 clusters->back()->setIndex(high->
cluster());
470 clusters->back()->towers().push_back(high);
476 std::stable_partition(towers->begin(), towers->end(),
477 std::bind2nd(std::ptr_fun(&towerIsNeighbor),
480 neighbors->insert(neighbors->end(), towers->begin(), neighborEnd);
481 towers->erase(towers->begin(), neighborEnd);
483 neighbors->push_back(high);
489 auto towerIter = towers->begin();
490 while (towerIter != towers->end()) {
493 if (!couldBePeakTower(*towerIter, neighbors)) {
494 neighbors->push_back(*towerIter);
495 towers->erase(towerIter++);
501 return clusters->size();
504 unsigned StFmsClusterFinder::associateTowersWithClusters(
505 TowerList* neighbors,
506 ClusterList* clusters,
507 TObjArray* valleys)
const {
508 TowerList associated;
511 TowerConstRIter tower;
512 for (tower = neighbors->rbegin(); tower != neighbors->rend(); ++tower) {
514 std::unique_ptr<TowerClusterAssociation> association(
new TowerClusterAssociation(*tower,mDetectorId));
515 for (
auto i = clusters->begin(); i != clusters->end(); ++i) {
516 association->add(i->get(), kPeakTower);
519 if (association->clusters()->size() == 1) {
521 association->clusters()->front()->towers().push_back(*tower);
522 associated.push_back(*tower);
523 }
else if (association->clusters()->size() > 1) {
526 valleys->Add(association.release());
527 associated.push_back(*tower);
531 for (
auto i = associated.begin(); i != associated.end(); ++i) {
532 neighbors->remove(*i);
534 return associated.size();
537 unsigned StFmsClusterFinder::associateValleyTowersWithClusters(
538 TowerList* neighbors,
539 ClusterList* clusters,
540 TObjArray* valleys)
const {
541 unsigned size = neighbors->size();
542 for (Int_t i(0); i < valleys->GetEntriesFast(); ++i) {
543 TowerClusterAssociation* association =
static_cast<TowerClusterAssociation*
>(valleys->At(i));
544 StFmsTowerCluster* cluster = association->nearestCluster();
547 association->tower()->setCluster(cluster->index());
548 cluster->towers().push_back(association->tower());
550 LOG_INFO <<
"Something is wrong! The following \"Valley\" tower does "
551 <<
"not belong to any cluster! Error!" << endm;
552 association->tower()->Print();
555 return size - neighbors->size();
558 unsigned StFmsClusterFinder::associateResidualTowersWithClusters(
559 TowerList* neighbors,
560 ClusterList* clusters)
const {
561 TowerList associated;
562 TowerConstRIter tower;
563 for (tower = neighbors->rbegin(); tower != neighbors->rend(); ++tower) {
565 TowerClusterAssociation association(*tower,mDetectorId);
566 for (
auto i = clusters->begin(); i != clusters->end(); ++i) {
570 association.add(i->get(), kClusterCenter);
572 if (!association.clusters()->empty()) {
573 StFmsTowerCluster* cluster = association.clusters()->front();
574 (*tower)->setCluster(cluster->index());
575 cluster->towers().push_back(*tower);
576 associated.push_back(*tower);
579 for (
auto i = associated.begin(); i != associated.end(); ++i) {
580 neighbors->remove(*i);
582 return associated.size();
585 void StFmsClusterFinder::associateSubThresholdTowersWithClusters(
587 ClusterList* clusters)
const {
588 for (
auto tower = towers->begin(); tower != towers->end(); ++tower) {
589 TowerClusterAssociation association(*tower,mDetectorId);
591 for (
auto i = clusters->begin(); i != clusters->end(); ++i) {
592 association.add(i->get(), kPeakTower);
594 StFmsTowerCluster* cluster = association.nearestCluster();
595 if (cluster && association.separation(cluster, kClusterCenter) < 0.3) {
596 (*tower)->setCluster(cluster->index());
597 cluster->towers().push_back(*tower);
StFmsClusterFinder(double energyCutoff=0.5)
Bool_t isNeighbor(const StFmsTower &tower) const
Could be 1- or 2-photon, needs to be fitted.
A cluster created by 2 photons.
virtual ~StFmsClusterFinder()
const StFmsHit * hit() const
int categorise(StFmsTowerCluster *cluster)
Declaration of StFmsTower, a simple FMS tower wrapper.
std::list< StFmsTower * > Towers
Shorthand for tower collection.
void calculateClusterMoments(StFmsTowerCluster *cluster) const
double separation(const StFmsTowerCluster *cluster, const ETowerClusterDistance distance)
Declaration of StFmsTowerCluster, a cluster of FMS towers.
int findClusters(TowerList *towers, ClusterList *clusters, int detetorId)
double separation(const StFmsTower *tower)
TowerClusterAssociation(StFmsTower *tower, int detectorId)
void calculateClusterMoments(Double_t energyCutoff)
bool canAssociate(const StFmsTowerCluster *cluster)
const StFmsTower * tower() const
void setCluster(Int_t cluster)
A cluster created by 1 photon.
std::list< StFmsTowerCluster * > * clusters()
StFmsTowerCluster * nearestCluster()
void add(StFmsTowerCluster *cluster, const ETowerClusterDistance distance)
void associate(StFmsTowerCluster *cluster)
Declaration of StFmsClusterFinder, an FMS tower clustering algorithm.