53 #include "StFmsDbMaker/StFmsDbMaker.h"
65 #include "St_base/StMessMgr.h"
66 #include "StEvent/StFmsHit.h"
70 #include "StFmsConstant.h"
73 const Int_t kMaxNPhotons = 7;
76 int mshowershapewithangle=1;
79 void setOption(
int v1,
int v2 ,
double v3){
80 mshowershapewithangle=v1;
87 double a11=0.998438;
double a12=0.222782;
double a13=-0.22122;
double b11=0.177028;
double b12=0.000473222;
double b13=0.178897;
double w1 = 0.0372556;
88 double a21=1.07711 ;
double a22=-0.0281385;
double a23=-0.0489747;
double b21=0.199964;
double b22=3.5021;
double b23=2.35246;
double w2 = 0.202699;
89 double a31=1.07901 ;
double a32=0.0650143;
double a33=-0.144025;
double b31=0.446845;
double b32=0.00544512;
double b33=1.64565;
double w3 = 0.293878;
90 double a41=0.922174;
double a42=0.0778254;
double a43=1.07474e-07;
double b41=0.593804;
double b42=0.6199;
double b43=3.49798;
double w4 = 0.236854;
91 double a51=0.999849;
double a52=0.000151185;
double a53=2.20244e-07;
double b51=0.949953;
double b52=1.84451;
double b53=3.40799;
double w5 = 0.146041;
92 double a61=0.997454;
double a62=0.00254497;
double a63=1.02127e-06;
double b61=1.43387;
double b62=2.91155;
double b63=3.4484;
double w6 = 0.0832717;
96 double a1S[6]={0.0303644,0.212191,0.277429,0.0370035,0.0524404,0.00844062};
97 double a2S[6]={0.00122867,0.105355,0.10538,0.152656,0.00664331,0.0108688};
98 double b1S[6]={0.403493,0.514546,0.672826,1.82344,0.727991,1.48785};
99 double b2S[6]={0.270492,0.514593,0.672655,0.644871,4.32003,0.25};
103 double a1L[6]={0.0275364,0.200363,0.277157,0.0391611,0.0590757,0.0101089};
104 double a2L[6]={0.000429808,0.0991777,0.104781,0.161916,0.00764026,0.012653};
105 double b1L[6]={0.515974,0.661722,0.865167,2.35237,0.932038,1.87933};
106 double b2L[6]={0.53531,0.661519,0.865226,0.828017,5.49041,0.321139};
108 double a1[6]={0. , 0 , 0. , 0. , 0. , 0. };
109 double a2[6]={0. , 0 , 0. , 0. , 0. , 0. };
110 double b1[6]={0. , 0. , 0. , 0. , 0. , 0. };
111 double b2[6]={0. , 0. , 0. , 0. , 0. , 0. };
112 double a3[6]={0. , 0 , 0. , 0. , 0. , 0. };
113 double b3[6]={0. , 0. , 0. , 0. , 0. , 0. };
114 double w[6]={1. , 1. , 1. , 1. , 1. , 1. };
116 std::array<double,60 > fitParameters;
117 void clear_fitParameters(){
118 for (
int i=0 ; i<60 ; i++) { fitParameters[i]=0 ; }
121 void choose_fitParameters(
int detID,
float scl=1.0){
122 if (detID<=9) {unused=5;}
124 if ( mshowershapewithangle==2 ) {
125 fitParameters= {unused, a11, a12, a13, b11*scl, b12*scl, b13*scl, w1 ,unused, unused,
126 unused, a21, a22, a23, b21*scl, b22*scl, b23*scl, w2 ,unused, unused,
127 unused, a31, a32, a33, b31*scl, b32*scl, b33*scl, w3 ,unused, unused,
128 unused, a41, a42, a43, b41*scl, b42*scl, b43*scl, w4 ,unused, unused,
129 unused, a51, a52, a53, b51*scl, b52*scl, b53*scl, w5 ,unused, unused,
130 unused, a61, a62, a63, b61*scl, b62*scl, b63*scl, w6 ,unused, unused };
131 }
else if ( mshowershapewithangle==1 ) {
133 for (
int i=0 ; i<6 ; i++) {
140 for (
int i=0 ; i<6 ; i++) {
147 fitParameters= { unused, a1[0], a2[0], a3[0], b1[0], b2[0], b3[0], w[0] ,unused, unused,
148 unused, a1[1], a2[1], a3[1], b1[1], b2[1], b3[1], w[1] ,unused, unused,
149 unused, a1[2], a2[2], a3[2], b1[2], b2[2], b3[2], w[2] ,unused, unused,
150 unused, a1[3], a2[3], a3[3], b1[3], b2[3], b3[3], w[3] ,unused, unused,
151 unused, a1[4], a2[4], a3[4], b1[4], b2[4], b3[4], w[4] ,unused, unused,
152 unused, a1[5], a2[5], a3[5], b1[5], b2[5], b3[5], w[5] ,unused, unused};
153 }
else if( mshowershapewithangle==0 ) {
154 fitParameters[1] = SS_A1;
155 fitParameters[2] = SS_A2;
156 fitParameters[3] = SS_A3;
157 fitParameters[4] = SS_B1 * scl;
158 fitParameters[5] = SS_B2 * scl;
159 fitParameters[6] = SS_B3 * scl;
163 TF2 showerShapeFitFunction(
"showerShapeFitFunction",
165 -25.0, 25.0, -25.0, 25.0, fitParameters.size());
171 std::vector<double> defaultMinuitStepSizes() {
172 std::vector<double> steps(1, 0.);
174 for (
int i(0); i < kMaxNPhotons; ++i) {
175 steps.insert(steps.end(), {0.1, 0.1, 0.2});
180 std::vector<double> towerWidths;
184 return energy + tower->
hit()->energy();
189 namespace FMSCluster {
192 Double_t StFmsClusterFitter::mEnergySum(0.0);
195 Int_t detectorId, Float_t xw, Float_t yw,
196 Float_t scaleShowerShapeLarge , Float_t scaleShowerShapeSmall,
197 Int_t ShowerShapeWithAngle, Int_t MergeSmallToLarge,
double vertexZ)
198 : mMinuit(3 * kMaxNPhotons + 1),
199 mScaleShowerShapeLarge(scaleShowerShapeLarge), mScaleShowerShapeSmall(scaleShowerShapeSmall),
200 mShowerShapeWithAngle(ShowerShapeWithAngle) , mMergeSmallToLarge(MergeSmallToLarge){
203 towerWidths.push_back(xw);
204 towerWidths.push_back(yw);
206 setOption(mShowerShapeWithAngle,mMergeSmallToLarge ,vertexZ);
207 clear_fitParameters();
208 choose_fitParameters(detectorId);
209 showerShapeFitFunction.SetParameters(fitParameters.data());
210 mMinuit.SetPrintLevel(-1);
216 return &showerShapeFitFunction;
220 const std::vector<double>& steps,
221 const std::vector<double>& lower,
222 const std::vector<double>& upper,
223 PhotonList* photons) {
224 Double_t chiSquare(-1.);
226 if (!StFmsClusterFitter::mTowers) {
227 LOG_ERROR <<
"no tower data available! return -1!" << endm;
230 mMinuit.SetFCN(minimizationFunctionNPhoton);
231 int nPhotons = parameters.size() / 3;
232 if (nPhotons < 1 || nPhotons > kMaxNPhotons) {
233 LOG_ERROR <<
"Number of photons must be between 1 and " << kMaxNPhotons <<
234 "not " << nPhotons <<
" for fit. Setting it to be 1..." << endm;
240 setMinuitParameter(0,
"nph", parameters, steps, lower, upper);
242 for (Int_t i = 0; i < nPhotons; i++) {
244 setMinuitParameter(j++, Form(
"x%d", i), parameters, steps, lower, upper);
245 setMinuitParameter(j++, Form(
"y%d", i), parameters, steps, lower, upper);
246 setMinuitParameter(j++, Form(
"E%d", i), parameters, steps, lower, upper);
250 if (nPhotons==1) {mMinuit.FixParameter(3) ; }
251 if (nPhotons==2) {mMinuit.FixParameter(3) ; mMinuit.FixParameter(6); }
253 runMinuitMinimization();
255 if (mMinuit.GetStatus() == 0) {
257 std::vector<double>
params(parameters.size(), 0.);
258 std::vector<double> errors(parameters.size(), 0.);
259 readMinuitParameters(params, errors);
260 for (
unsigned i(1); i < parameters.size(); i += 3) {
261 photons->emplace_back(params.at(i), params.at(i + 1), params.at(i + 2));
264 mMinuit.Eval(photons->size(),
nullptr, chiSquare, params.data(), 1);
270 const std::vector<double>& lower,
271 const std::vector<double>& upper,
272 PhotonList* photons) {
273 return fitNPhoton(parameters, defaultMinuitStepSizes(),
274 lower, upper, photons);
309 const std::array<double, 7>& steps,
310 const std::array<double, 7>& lower,
311 const std::array<double, 7>& upper,
312 PhotonList* photons) {
313 Double_t chiSquare(-1.);
314 if (!StFmsClusterFitter::mTowers) {
315 LOG_ERROR <<
"no tower data available! return -1!" << endm;
318 mMinuit.SetFCN(minimizationFunction2Photon);
320 const std::vector<TString> names = {
321 "nph",
"xPi",
"yPi",
"d_gg",
"theta",
"z_gg",
"E_gg"
323 for (
unsigned i = 0; i < names.size(); ++i) {
324 setMinuitParameter(i, names.at(i), parameters, steps, lower, upper);
327 mMinuit.FixParameter(4);
328 mMinuit.FixParameter(6);
329 runMinuitMinimization();
330 if (mMinuit.GetStatus() == 0) {
333 std::vector<double> param(parameters.size(), 0.);
334 std::vector<double> error(parameters.size(), 0.);
335 readMinuitParameters(param, error);
339 double x = param[1] + cos(param[4]) * param[3] * (1 - param[5]) / 2.0;
340 double y = param[2] + sin(param[4]) * param[3] * (1 - param[5]) / 2.0;
341 double E = param[6] * (1 + param[5]) / 2.0;
342 photons->emplace_back(x, y, E);
344 x = param[1] - cos(param[4]) * param[3] * (1 + param[5]) / 2.0;
345 y = param[2] - sin(param[4]) * param[3] * (1 + param[5]) / 2.0;
346 E = param[6] * (1 - param[5]) / 2.0;
347 photons->emplace_back(x, y, E);
349 mMinuit.Eval(7,
nullptr, chiSquare, param.data(), 1);
355 Double_t* parameters) {
362 if(mshowershapewithangle==0){
363 double w = parameters[0];
364 for (
int ix = 0; ix < 2; ++ix) {
365 for (
int iy = 0; iy < 2; ++iy) {
366 double signX = std::pow(-1., ix);
367 double signY = std::pow(-1., iy);
368 std::array<double, 2> s{ {xy[0] + signX * w / 2.,
369 xy[1] + signY * w / 2.} };
370 energy += signX * signY * energyDepositionDistribution(s.data(),
377 Double_t ZcS[6] = {720.45,727.95,735.45,742.95,750.45,757.95};
378 Double_t ZcL[6] = {722.98,733.01,743.04,753.07,763.10,773.13};
379 Double_t Zmax,xoff,yoff;
380 if (parameters[0]>4) {
381 yoff=98.8; Zmax=735.45; xoff=0.3; Zc=ZcL;
383 yoff=46.5; Zmax=735.45; xoff=0.93; Zc=ZcS;
385 if (mmerge >0) yoff=98.8;
387 Double_t tany = ( yoff - xy[3]) / (Zmax - vertexz);
388 Double_t tanx = ( xy[1]- xoff ) / (Zmax - vertexz);
390 for(Int_t i = 0; i < 6; i++){
391 Double_t xc = xy[1] + tanx*(Zc[i] - Zmax);
392 Double_t yc = xy[3] - tany*(Zc[i] - Zmax);
394 energy += energyDepositionInTowerSingleLayer(xy[0]-xc,xy[2]-yc,¶meters[istart]) * parameters[istart+7] ;
404 int StFmsClusterFitter::runMinuitMinimization() {
405 std::vector<double> arguments = {1000., 1.};
407 mMinuit.mnexcm(
"MIGRAD", arguments.data(), arguments.size(), errorFlag);
410 if (mMinuit.GetNumFixedPars() > 0) {
418 Double_t StFmsClusterFitter::energyDepositionDistribution(
420 Double_t* parameters) {
425 for (
int i = 1; i < 4; i++) {
426 f += showerShapeComponent(xy[0], xy[1], parameters[i], parameters[i + 3]);
428 return f / TMath::TwoPi();;
433 void StFmsClusterFitter::minimizationFunctionNPhoton(Int_t& npara,
441 const int nPhotons =
static_cast<int>(para[0]);
443 for (
auto i = mTowers->begin(), e = mTowers->end(); i!=e; ++i){
444 const StFmsTower* tower = *i;
463 Double_t x=tower->x();
464 Double_t y=tower->y();
465 fitParameters.front() = tower->w();
468 for (
int j = 0; j < nPhotons; ++j) {
471 if(mshowershapewithangle>0 ){ expected += para[k + 3] *
474 if(mshowershapewithangle==0 ){ expected += para[k + 3] *
480 const double measured = tower->e();
481 const double deviation = measured - expected;
489 const Double_t ratio = measured / mEnergySum;
491 const Double_t err = 0.03 *
492 pow(ratio, 1. - 0.001 * mEnergySum) *
493 pow(1. - ratio, 1. - 0.007 * mEnergySum) *
496 fval += deviation * deviation / err;
500 fval = std::max(fval, 0.);
506 void StFmsClusterFitter::minimizationFunction2Photon(Int_t& nparam,
512 const double dgg = param[3];
513 const double zgg = param[5];
514 const double angle = param[4];
515 std::array<double, 7> oldParam{ {
517 param[1] + cos(angle) * dgg * (1 - zgg) / 2.0,
518 param[2] + sin(angle) * dgg * (1 - zgg) / 2.0,
519 param[6] * (1 + zgg) / 2.0,
520 param[1] - cos(angle) * dgg * (1 + zgg) / 2.0,
521 param[2] - sin(angle) * dgg * (1 + zgg) / 2.0,
522 param[6] * (1 - zgg) / 2.0
525 minimizationFunctionNPhoton(nparam, grad, fval, oldParam.data(), 0);
528 template<
class Container>
529 int StFmsClusterFitter::setMinuitParameter(
int index,
const TString& name,
531 const Container& steps,
532 const Container& lower,
533 const Container& upper) {
535 mMinuit.mnparm(index, name, params.at(index), steps.at(index),
536 lower.at(index), upper.at(index), error);
540 int StFmsClusterFitter::readMinuitParameters(std::vector<double>& parameters,
541 std::vector<double>& errors) {
542 errors.resize(parameters.size(), 0.);
543 for (
int i = 0, size = parameters.size(); i != size; ++i) {
544 mMinuit.GetParameter(i, parameters.at(i), errors.at(i));
546 return parameters.size();
551 mEnergySum = std::accumulate(mTowers->begin(), mTowers->end(), 0., addTowerEnergy);
554 int d=mTowers->front()->hit()->detectorId();
556 choose_fitParameters(d,mScaleShowerShapeLarge);
558 choose_fitParameters(d,mScaleShowerShapeSmall);
560 showerShapeFitFunction.SetParameters(fitParameters.data());
Declaration of StFmsClusterFitter, shower-shape fitting routine.
Int_t fit2Photon(const std::array< double, 7 > ¶meters, const std::array< double, 7 > &steps, const std::array< double, 7 > &lower, const std::array< double, 7 > &upper, PhotonList *photons)
const StFmsHit * hit() const
static Double_t energyDepositionInTowerOLD(Double_t x, Double_t y, Double_t *par)
Declaration of StFmsTower, a simple FMS tower wrapper.
std::list< StFmsTower * > Towers
Shorthand for tower collection.
static Double_t energyDepositionInTower(Double_t *x, Double_t *par)
static int maxNFittedPhotons()
Double_t fitNPhoton(const std::vector< double > ¶meteres, const std::vector< double > &steps, const std::vector< double > &lower, const std::vector< double > &up, PhotonList *photons)
void setTowers(StFmsTowerCluster::Towers *towers)
virtual ~StFmsClusterFitter()
TF2 * showerShapeFunction()