25 #include "StRoot/St_base/StMessMgr.h"
27 #include "StEvent/StFmsHit.h"
36 using namespace FMSCluster;
42 typedef Towers::const_iterator TowerIter;
45 int accumulatePhotons(
int nPhotons,
const ClusterList::value_type& cluster) {
46 return nPhotons + cluster->cluster()->nPhotons();
51 :
public std::unary_function<const ClusterList::value_type&, bool> {
53 IsBadCluster(
double minEnergy,
unsigned maxTowers)
54 : energy(minEnergy), towers(maxTowers) { }
55 bool operator()(
const ClusterList::value_type& cluster)
const {
56 return cluster->cluster()->energy() <= energy ||
57 cluster->towers().size() > towers;
74 photon = &(cluster->
photons()[0]);
78 photon = &(cluster->
photons()[0]);
80 photon = &(cluster->
photons()[1]);
93 const StFmsTower* searchClusterTowers(
int row,
int column,
96 const Towers& towers = cluster.
towers();
97 for (TowerIter i = towers.begin(); i != towers.end(); ++i) {
99 if (tower->
row() == row && tower->
column() == column) {
110 mGeometry = geometry;
111 mDetectorId = detectorId;
114 StFmsEventClusterer::~StFmsEventClusterer() {
120 Bool_t StFmsEventClusterer::cluster(std::vector<StFmsTower>* towerList) {
122 mClusterFinder.setMomentEnergyCutoff(.5);
123 mTowerWidthXY = mGeometry->
towerWidths(mDetectorId);
125 if (mTowers->size() > 578) {
126 LOG_ERROR <<
"Too many towers for Fit" << endm;
133 Int_t StFmsEventClusterer::fitEvent() {
136 std::vector<StFmsTower>::iterator towerIter;
137 for (towerIter = mTowers->begin(); towerIter != mTowers->end(); ++towerIter) {
138 towerList.push_back(&(*towerIter));
140 mClusterFinder.findClusters(&towerList, &mClusters);
142 if (mDetectorId == 8 || mDetectorId == 9) {
143 mClusters.remove_if(IsBadCluster(0.75, 25));
145 mClusters.remove_if(IsBadCluster(2.0, 49));
148 for (
ClusterIter i = mClusters.begin(); i != mClusters.end(); ++i) {
149 (*i)->findClusterAxis(mClusterFinder.momentEnergyCutoff());
153 bool badEvent =
false;
154 const double max2PhotonFitChi2 = 10.;
155 for (
ClusterIter cluster = mClusters.begin(); cluster != mClusters.end();
157 Int_t clustCatag = mClusterFinder.categorise(cluster->get());
160 mFitter->setTowers(&(*cluster)->towers());
164 fitOnePhoton(cluster->get());
167 fit2PhotonClust(cluster);
168 badEvent = (*cluster)->chiSquare() > max2PhotonFitChi2;
173 Bool_t is2Photon =
true;
174 double chiSq1 = fitOnePhoton(cluster->get());
182 chiSq2 = fit2PhotonClust(cluster);
184 if (validate2ndPhoton(cluster)) {
187 is2Photon = chiSq2 <= chiSq1;
197 (*cluster)->cluster()->setNPhotons(2);
198 (*cluster)->setChiSquare(chiSq2);
200 badEvent = (*cluster)->chiSquare() > max2PhotonFitChi2;
203 (*cluster)->cluster()->setNPhotons(1);
204 (*cluster)->setChiSquare(chiSq1);
205 (*cluster)->photons()[0] = photon;
209 LOG_ERROR <<
"Your logic of catagory is wrong! Something impossible " <<
210 "happens! This a catagory-" << clustCatag <<
211 " clusters! Don't know how to fit it!" << endm;
214 Int_t nPh = std::accumulate(mClusters.begin(), mClusters.end(), 0,
216 if (nPh > StFmsClusterFitter::maxNFittedPhotons()) {
218 LOG_WARN <<
"Can not fit " << nPh <<
" (more than " <<
219 StFmsClusterFitter::maxNFittedPhotons() <<
" photons!" << endm;
224 for (
ClusterIter cluster = mClusters.begin(); cluster != mClusters.end();
226 allTow.insert(allTow.end(), (*cluster)->towers().begin(),
227 (*cluster)->towers().end());
229 mFitter->setTowers(&allTow);
232 if (mClusters.size() > 1) {
233 globalFit(nPh, mClusters.size(), mClusters.begin());
236 Int_t iph = std::accumulate(mClusters.begin(), mClusters.end(), 0,
239 LOG_ERROR <<
"total nPh=" << nPh <<
" iPh=" << iph << endm;
245 Double_t StFmsEventClusterer::photonEnergyInCluster(
251 const Towers& towers = p_clust->
towers();
252 for (TowerIter tower = towers.begin(); tower != towers.end(); ++tower) {
253 eSS += photonEnergyInTower(widthLG, *tower, p_photon);
258 Double_t StFmsEventClusterer::photonEnergyInTower(
262 Double_t xx = ((Double_t)p_tower->
column() - 0.5) *
263 mTowerWidthXY[0] - p_photon->
xPos;
264 Double_t yy = ((Double_t)p_tower->
row() - 0.5) *
265 mTowerWidthXY[1] - p_photon->
yPos;
266 Double_t eSS = p_photon->
energy *
267 mFitter->showerShapeFunction()->Eval(xx, yy, 0);
276 const Double_t start[4] = {
277 1.0, mTowerWidthXY[0] * p_clust->
cluster()->
x(),
278 mTowerWidthXY[1] * p_clust->
cluster()->
y(),
281 const Double_t delta[4] = {
282 0.5, 0.5 * mTowerWidthXY[0], 0.5 * mTowerWidthXY[1],
286 Double_t lowLim[4], upLim[4];
287 for (
int i(0); i < 4; ++i) {
288 lowLim[i] = start[i] - delta[i];
289 upLim[i] = start[i] + delta[i];
292 Double_t chiSq = mFitter->fit(start, NULL, lowLim, upLim, &photons);
293 if (photons.empty()) {
294 LOG_ERROR <<
"1-photon Minuit fit returns error!" << endm;
296 p_clust->
photons()[0] = photons.back();
298 int ndf = p_clust->
towers().size() - 3;
306 Float_t StFmsEventClusterer::globalFit(
const Int_t nPh,
const Int_t nCl,
309 if (nPh > StFmsClusterFitter::maxNFittedPhotons() || nPh < 2) {
310 LOG_ERROR <<
"Global fit! Can not fit " << nPh <<
" photons!" << endm;
315 LOG_ERROR << nCl <<
" clusters! Global fit will NOT work!" << endm;
322 std::vector<double> start(1, 0.), lowLim(1, 0.), upLim(1, 0.);
333 std::advance(end, nCl);
334 for (
ClusterIter cluster = first; cluster != end; ++cluster) {
336 for (Int_t jp = 0; jp < (*cluster)->cluster()->nPhotons(); jp++) {
337 if (totPh > StFmsClusterFitter::maxNFittedPhotons()) {
338 LOG_ERROR <<
"Total # of photons in " << nCl <<
" clusters is at least "
339 << totPh <<
"! I can NOT do fit!" << endm;
344 start.push_back((*cluster)->photons()[jp].xPos);
345 lowLim.push_back(start.back() - 1.25);
346 upLim.push_back(start.back() + 1.25);
348 start.push_back((*cluster)->photons()[jp].yPos);
349 lowLim.push_back(start.back() - 1.25);
350 upLim.push_back(start.back() + 1.25);
352 start.push_back((*cluster)->photons()[jp].energy);
353 lowLim.push_back(start.back() * (1 - 0.3));
354 upLim.push_back(start.back() * (1 + 0.3));
359 start.front() = totPh;
360 lowLim.front() = 0.5;
361 upLim.front() = StFmsClusterFitter::maxNFittedPhotons() + 0.5;
363 LOG_WARN <<
"WARNING! Total # of photons in " << nCl <<
364 " clusters is at least " << totPh <<
"! Not the same as the nPh = "
365 << nPh <<
"! I will try " << totPh <<
" instead!" << endm;
368 Double_t chiSq = mFitter->fit(&start.at(0), NULL,
369 &lowLim.at(0), &upLim.at(0), &photons);
370 if (photons.empty()) {
371 LOG_WARN <<
"Global Minuit fit returns error!" << endm;
375 PhotonList::const_iterator photonIter = photons.begin();
376 for (
ClusterIter cluster = first; cluster != end; ++cluster) {
378 for (Int_t jp = 0; jp < (*cluster)->cluster()->nPhotons();
379 jp++, ++photonIter) {
380 (*cluster)->photons()[jp] = *photonIter;
387 Float_t StFmsEventClusterer::fit2PhotonClust(
ClusterIter p_clust) {
388 const Double_t step2[7] = {0, 0.02, 0.02, 0.01, 0.01, 0.01, 0.1};
389 Double_t ratioSigma = (*p_clust)->cluster()->sigmaMin() /
390 (*p_clust)->cluster()->sigmaMax();
391 Double_t maxTheta = ratioSigma / 2.8;
392 if (maxTheta > (TMath::Pi() / 2.0)) {
393 maxTheta = TMath::Pi() / 2.0;
396 Double_t EcSigmaMax = (*p_clust)->cluster()->energy() *
397 (*p_clust)->cluster()->sigmaMax();
399 Double_t start[7], lowLim[7], upLim[7];
414 start[1] = mTowerWidthXY[0] * (*p_clust)->cluster()->x();
415 start[2] = mTowerWidthXY[1] * (*p_clust)->cluster()->y();
416 start[6] = (*p_clust)->cluster()->energy();
417 start[4] = (*p_clust)->thetaAxis();
418 const float dggPara[6] = {18.0, 2.2, 0.5, 60.0, 0.085, 3.5};
419 start[3] = dggPara[1] * mTowerWidthXY[0] * (*p_clust)->cluster()->sigmaMax();
421 start[5] = 0.1 * (2 * gRandom->Rndm() - 1);
422 lowLim[1] = start[1] - 0.2 * mTowerWidthXY[0];
423 lowLim[2] = start[2] - 0.2 * mTowerWidthXY[1];
424 lowLim[6] = start[6] * (1. - 0.05);
425 upLim[1] = start[1] + 0.2 * mTowerWidthXY[0];
426 upLim[2] = start[2] + 0.2 * mTowerWidthXY[1];
427 upLim[6] = start[6] * (1. + 0.05);
428 lowLim[4] = start[4] - maxTheta;
430 lowLim[3] = dggPara[0] / pow(EcSigmaMax, 0.8);
431 if (lowLim[3] < dggPara[2]) {
432 lowLim[3] = dggPara[2];
434 lowLim[3] *= mTowerWidthXY[0];
435 if (lowLim[3] >= start[3]) {
436 lowLim[3] = start[3] * 0.9;
438 upLim[3] = dggPara[4] * (dggPara[3] - EcSigmaMax);
439 if (upLim[3] > dggPara[5]) {
440 upLim[3] = dggPara[5];
442 upLim[3] *= mTowerWidthXY[0];
443 if (upLim[3] <= start[3]) {
444 upLim[3] = start[3] * 1.1;
446 upLim[4] = start[4] + maxTheta;
450 Double_t chiSq = mFitter->fit2PhotonCluster(start, step2, lowLim, upLim,
452 if (photons.empty()) {
453 LOG_WARN <<
"Minuit fit returns error!" << endm;
457 (*p_clust)->photons()[0] = photons.front();
458 (*p_clust)->photons()[1] = photons.back();
459 (*p_clust)->cluster()->setNPhotons(photons.size());
460 chiSq = globalFit(2, 1, p_clust);
461 int ndf = (*p_clust)->towers().size() - 6;
465 (*p_clust)->setChiSquare(chiSq / ndf);
466 return (*p_clust)->chiSquare();
484 int column = 1 + (Int_t)(photon->
xPos / mTowerWidthXY[0]);
485 int row = 1 + (Int_t)(photon->
yPos / mTowerWidthXY[1]);
488 const StFmsTower* tower = searchClusterTowers(row, column, **cluster);
495 if (tower->
hit()->energy() < 0.25 * photon->
energy) {
500 Double_t eSS = photonEnergyInTower(mTowerWidthXY[0], tower, photon);
501 if (tower->
hit()->energy() > 1.5 * eSS) {
508 Double_t energyInOwnCluster =
509 photonEnergyInCluster(mTowerWidthXY[0], cluster->get(), photon);
513 if (photonEnergyInCluster(mTowerWidthXY[0], i->get(), photon) >
514 (0.2 * energyInOwnCluster)) {
A cluster created by 2 photons.
A cluster created by 1 photon.
Declaration of StFmsGeometry, an FMS database geometry interface.
Declaration of StFmsCluster, a group of adjacent FMS hits.
Float_t xPos
Fitted (relative) x-position.
Declaration of StFmsTower, a simple FMS tower wrapper.
ClusterList::iterator ClusterIter
void setChiSquare(Float_t chi2)
Declaration of StFmsClusterFitter, shower-shape fitting routine.
Float_t energy
Fitted energy.
Declaration of StFmsEventClusterer, manager class for clustering.
std::list< FMSCluster::StFmsTower * > TowerList
std::list< StFmsTower * > Towers
Shorthand for tower collection.
Declaration of StFmsTowerCluster, a cluster of FMS towers.
Bool_t setNPhotons(Int_t nPhoton)
StFmsFittedPhoton * photons()
Declaration of StFmsFittedPhoton, a photon fitted to an FMS cluster.
const StFmsHit * hit() const
ClusterList::const_iterator ClusterConstIter
Float_t yPos
Fitted (relative) y-position.
std::vector< Float_t > towerWidths(Int_t detectorId) const
std::list< StFmsFittedPhoton > PhotonList
Float_t chiSquare() const
Could be 1- or 2-photon, needs to be fitted.