00001 #include "BDProfMon.h"
00002
00003 #include <Conventions/Munits.h>
00004
00005 #include <cmath>
00006 #include <string>
00007 #include <cassert>
00008 #include <TMinuit.h>
00009 #include <TSystem.h>
00010 #include <TF1.h>
00011 #include <MessageService/MsgService.h>
00012 CVSID("$Id: BDProfMon.cxx,v 1.10 2008/11/07 16:46:04 bv Exp $");
00013
00014 using namespace std;
00015
00016
00017 BDProfMon::BDProfMon()
00018 : BDSwicDevice(), fSpacing(0)
00019 {
00020 }
00021 BDProfMon::BDProfMon(const RawBeamData& swic_data)
00022 : BDSwicDevice(swic_data), fSpacing(0)
00023 {
00024 this->UpdateCache();
00025 }
00026 BDProfMon::~BDProfMon()
00027 {
00028 }
00029
00030 void BDProfMon::UpdateCache()
00031 {
00032 if (!this->IsValid()) return;
00033 RawBeamData& rbd = this->GetData();
00034 string name = rbd.GetName();
00035 if (name == "E:M121DS" || name == "E:MTGTDS")
00036 fSpacing = 0.5*Munits::mm;
00037 else
00038 fSpacing = 1.0*Munits::mm;
00039 }
00040
00041 void BDProfMon::SetData(const RawBeamData& swic_data)
00042 {
00043 this->BDSwicDevice::SetData(swic_data);
00044 this->UpdateCache();
00045 }
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 bool BDProfMon::SetMask(const std::vector<double>& cmask)
00057 {
00058 vector<double> mask = cmask;
00059
00060 const int unused[] = {0,1, 46,47, 48,49, 95, 95, -1} ;
00061 for (int ind=0; unused[ind] >= 0; ++ind) mask[ind] = 0.0;
00062 return this->BDSwicDevice::SetMask(mask);
00063 }
00064 int BDProfMon::Xindex(int channel)
00065 {
00066 if (channel<1 || channel > 44) return -1;
00067 return channel+1;
00068 }
00069 int BDProfMon::Yindex(int channel)
00070 {
00071 if (channel<1 || channel > 44) return -1;
00072 return channel+49;
00073 }
00074 double BDProfMon::WirePosition(int channel) const
00075 {
00076 return (channel-22.5)*fSpacing;
00077 }
00078 double BDProfMon::GetStats(double& xmean, double &ymean, double &xrms, double &yrms) const
00079 {
00080 double qx=0,qx2=0,qtotx=0;
00081 double qy=0,qy2=0,qtoty=0;
00082 for (int ch = 1; ch <= 44; ++ch) {
00083 double X = this->WirePosition(ch);
00084 double Y = X;
00085
00086 int x_index = this->Xindex(ch);
00087 int y_index = this->Yindex(ch);
00088
00089 double Qx = this->GetVoltage(x_index);
00090 double Qy = this->GetVoltage(y_index);
00091
00092 Qx = Qx > 0 ? Qx : 0;
00093 Qy = Qy > 0 ? Qy : 0;
00094
00095 qtotx += Qx;
00096 qtoty += Qy;
00097
00098 qx += Qx*X;
00099 qy += Qy*Y;
00100
00101 qx2 += Qx*X*X;
00102 qy2 += Qy*Y*Y;
00103 }
00104 if (qtotx == 0.0) {
00105 xmean = 0;
00106 xrms = 0;
00107 }
00108 else {
00109 xmean = qx/qtotx;
00110 double tmp = qx2/qtotx-xmean*xmean;
00111 if (tmp>0.0) xrms = sqrt(tmp);
00112 else xrms=0;
00113 }
00114 if (qtoty == 0.0) {
00115 ymean = 0;
00116 yrms = 0;
00117 }
00118 else {
00119 ymean = qy/qtoty;
00120 double tmp = qy2/qtoty-ymean*ymean;
00121 if (tmp > 0.0) yrms = sqrt(tmp);
00122 else yrms = 0;
00123 }
00124 return qtotx+qtoty;
00125 }
00126
00127
00128 double BDProfMon::GetStats(TGraphErrors *prof, double& mean, double& rms) const {
00129
00130 double qx=0,qx2=0,qtotx=0;
00131
00132 for (int i = 0; i < prof->GetN(); i++) {
00133 double X = prof->GetX()[i];
00134 double Qx = prof->GetY()[i];
00135 qtotx += Qx;
00136 qx += Qx*X;
00137 qx2 += Qx*X*X;
00138 }
00139 if (qtotx == 0.0) {
00140 mean = 0;
00141 rms = 0;
00142 }
00143 else {
00144 mean = qx/qtotx;
00145 double tmp = qx2/qtotx-mean*mean;
00146 if (tmp>0.0) rms = sqrt(tmp);
00147 else rms=0;
00148 }
00149 return qtotx;
00150 }
00151
00152 double BDProfMon::GetGaussFit(double& xmean, double &ymean, double &xsigma, double &ysigma) const
00153 {
00154 TGraphErrors xProf,yProf;
00155
00156 xProf.Clear("");
00157 yProf.Clear("");
00158 int nxpoints = 0, nypoints = 0;
00159
00160 for (int ch = 1; ch <= 44; ++ch) {
00161
00162 double X = this->WirePosition(ch);
00163 double Y = X;
00164
00165 int x_index = this->Xindex(ch);
00166 int y_index = this->Yindex(ch);
00167
00168 double Qx = this->GetVoltage(x_index);
00169 double Qy = this->GetVoltage(y_index);
00170
00171
00172 Qx = Qx > 0 ? Qx : 0;
00173 Qy = Qy > 0 ? Qy : 0;
00174
00175
00176 double xNoise = this->GetNoise(x_index);
00177 double yNoise = this->GetNoise(y_index);
00178
00179 xNoise = xNoise > 0 ? xNoise : 1.0*Munits::millivolt;
00180 yNoise = yNoise > 0 ? yNoise : 1.0*Munits::millivolt;
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 xProf.SetPoint(nxpoints,X/Munits::mm,Qx/Munits::millivolt);
00192
00193 xProf.SetPointError(nxpoints,0.0,xNoise/Munits::millivolt);
00194 nxpoints++;
00195
00196 yProf.SetPoint(nypoints,Y/Munits::mm,Qy/Munits::millivolt);
00197
00198 yProf.SetPointError(nypoints,0.0,yNoise/Munits::millivolt);
00199 nypoints++;
00200
00201 }
00202
00203
00204 SuppressDeadHot(&xProf);
00205 SuppressDeadHot(&yProf);
00206
00207
00208
00209
00210 TF1 gausF("gausF","[0]*exp((-1*(x-[1])*(x-[1]))/(2*[2]*[2]))/(sqrt(2*3.142)*[2])");
00211
00212 gausF.SetParName(0,"Area");
00213 gausF.SetParName(1,"Mean");
00214 gausF.SetParName(2,"Sigma");
00215
00216
00217
00218 gausF.SetParameter(0,2000);
00219 gausF.SetParameter(1,0.0);
00220 gausF.SetParameter(2,0.5);
00221
00222
00223 gausF.SetParLimits(0,0.00,100000000);
00224 gausF.SetParLimits(2,0.0001,1000);
00225
00226
00227
00228
00229 double xarea,yarea;
00230 double xStatMean,yStatMean,xrms,yrms;
00231
00232 xarea = -999;
00233 xmean = -999;
00234 xsigma = -999;
00235 xarea = -999;
00236 ymean = -999;
00237 ysigma = -999;
00238
00239
00240
00241 xarea = GetStats(&xProf,xStatMean,xrms);
00242 xarea*=Munits::millivolt;
00243
00244 MSG("BD",Msg::kVerbose) << "X profile data" << endl;
00245 for (int i = 0; i<xProf.GetN(); i++)
00246 MSG("BD",Msg::kVerbose) << "x[" << i << "] = " <<xProf.GetX()[i]
00247 << " y[" << i << "] = " <<xProf.GetY()[i]
00248 << " ex[" << i << "] = " <<xProf.GetErrorX(i)
00249 << " ey[" << i << "] = " <<xProf.GetErrorY(i)
00250 << endl;
00251
00252
00253
00254 MSG("BD",Msg::kVerbose) << endl;
00255 MSG("BD",Msg::kVerbose) << "X charge (V) : " << xarea << endl;
00256 MSG("BD",Msg::kVerbose) << "X stat mean : " << xStatMean << endl;
00257 MSG("BD",Msg::kVerbose) << "X rms : " << xrms << endl;
00258
00259
00260
00261
00262 if (xProf.GetN() > 5 &&
00263 xarea > 100*Munits::millivolt &&
00264 fabs(xStatMean) < 20*fSpacing/Munits::mm &&
00265 fabs(xrms) < 11*fSpacing/Munits::mm) {
00266 gausF.SetParameter(0,xarea/Munits::millivolt);
00267 gausF.SetParameter(1,xStatMean);
00268 gausF.SetParameter(2,xrms*0.6);
00269 gausF.SetParameter(3,0.5);
00270 gausF.SetParameter(4,0.0);
00271 if (xProf.Fit("gausF","q","",-22*fSpacing/Munits::mm,22*fSpacing/Munits::mm) == 0) {
00272 gMinuit->Command("set str 2");
00273
00274
00275
00276 bool goodfit = true;
00277
00278
00279 if (gausF.GetParameter(0) < 10)
00280 goodfit = false;
00281 if (fabs(gausF.GetParameter(1)) > 22*fSpacing/Munits::mm)
00282 goodfit = false;
00283 if (gausF.GetParameter(2) > 22*fSpacing/Munits::mm ||
00284 gausF.GetParameter(2) < 0.0)
00285 goodfit = false;
00286
00287 if (goodfit) {
00288 xarea = gausF.GetParameter(0)/fSpacing*Munits::mm*Munits::millivolt;
00289 xmean = gausF.GetParameter(1)*Munits::mm;
00290 xsigma = gausF.GetParameter(2)*Munits::mm;
00291 if (xProf.Fit("gausF","q E M","",-22*fSpacing/Munits::mm,22*fSpacing/Munits::mm) == 0){
00292 gMinuit->Command("set str 1");
00293
00294
00295 xarea = gausF.GetParameter(0)/fSpacing*Munits::mm*Munits::millivolt;
00296 xmean = gausF.GetParameter(1)*Munits::mm;
00297 xsigma = gausF.GetParameter(2)*Munits::mm;
00298 }
00299 }
00300
00301
00302 }
00303 }
00304
00305
00306
00307
00308
00309 yarea = GetStats(&yProf,yStatMean,yrms);
00310 yarea*=Munits::millivolt;
00311
00312
00313 MSG("BD",Msg::kVerbose) << "Y profile data" << endl;
00314 for (int i = 0; i<yProf.GetN(); i++)
00315 MSG("BD",Msg::kVerbose) << "x[" << i << "] = " <<yProf.GetX()[i]
00316 << " y[" << i << "] = " <<yProf.GetY()[i]
00317 << " ex[" << i << "] = " <<yProf.GetErrorX(i)
00318 << " ey[" << i << "] = " <<yProf.GetErrorY(i)
00319 << endl;
00320
00321
00322 MSG("BD",Msg::kVerbose) << endl;
00323 MSG("BD",Msg::kVerbose) << "Y charge (V) : " << yarea << endl;
00324 MSG("BD",Msg::kVerbose) << "Y stat mean : " << yStatMean << endl;
00325 MSG("BD",Msg::kVerbose) << "Y rms : " << yrms << endl;
00326
00327
00328 if (yProf.GetN() > 5 &&
00329 yarea > 100*Munits::millivolt &&
00330 fabs(yStatMean) < 20*fSpacing/Munits::mm &&
00331 fabs(yrms) < 11*fSpacing/Munits::mm) {
00332
00333 gausF.SetParameter(0,yarea/Munits::millivolt);
00334 gausF.SetParameter(1,yStatMean);
00335 gausF.SetParameter(2,yrms*0.6);
00336 gausF.SetParameter(3,0.5);
00337 gausF.SetParameter(4,0.0);
00338
00339 if (yProf.Fit("gausF","q","",-22*fSpacing/Munits::mm,22*fSpacing/Munits::mm) == 0) {
00340 gMinuit->Command("set str 2");
00341
00342
00343
00344 bool goodfit=true;
00345
00346
00347 if (gausF.GetParameter(0) < 10)
00348 goodfit = false;
00349 if (fabs(gausF.GetParameter(1)) > 22*fSpacing/Munits::mm)
00350 goodfit = false;
00351 if (gausF.GetParameter(2) > 22*fSpacing/Munits::mm ||
00352 gausF.GetParameter(2) < 0.0)
00353 goodfit = false;
00354 if (goodfit) {
00355 yarea = gausF.GetParameter(0)/fSpacing*Munits::mm*Munits::millivolt;
00356 ymean = gausF.GetParameter(1)*Munits::mm;
00357 ysigma = gausF.GetParameter(2)*Munits::mm;
00358
00359 if (yProf.Fit("gausF","q E M","",-22*fSpacing/Munits::mm,22*fSpacing/Munits::mm) == 0){
00360 gMinuit->Command("set str 1");
00361 yarea = gausF.GetParameter(0)/fSpacing*Munits::mm*Munits::millivolt;
00362 ymean = gausF.GetParameter(1)*Munits::mm;
00363 ysigma = gausF.GetParameter(2)*Munits::mm;
00364 }
00365 }
00366
00367
00368 }
00369 }
00370
00371
00372
00373
00374
00375
00376 double totarea=0;
00377
00378 totarea=this->GetStats(xStatMean,yStatMean,xrms,yrms);
00379
00380 MSG("BD",Msg::kVerbose) << "Total area "
00381 << totarea
00382 << " Prof Means = "
00383 << xStatMean << ","
00384 << yStatMean
00385 << " RMS = "
00386 << xrms << ","
00387 << yrms << endl;
00388
00389
00390 MSG("BD",Msg::kVerbose) << "Fitted area "
00391 << xarea+yarea
00392 << " Gauss Means = "
00393 << xmean << ","
00394 << ymean
00395 << " Gaus sigmas = "
00396 << xsigma << ","
00397 << ysigma << endl;
00398
00399 return xarea+yarea;
00400 }
00401
00402 void BDProfMon::SuppressDeadHot(TGraphErrors *prof) const
00403 {
00404
00405
00406 if (prof->GetN() > 1) {
00407 if (prof->GetY()[0] > 10*prof->GetY()[1])
00408 prof->RemovePoint(0);
00409 if (prof->GetY()[prof->GetN()-1] > 10*prof->GetY()[prof->GetN()-2])
00410 prof->RemovePoint(prof->GetN()-1);
00411 }
00412
00413
00414
00415 for (int i = 1; i < prof->GetN()-1; i++) {
00416 double average = (prof->GetY()[i-1]+prof->GetY()[i+1])/2.0;
00417 if (prof->GetY()[i] < 0.1*average ||
00418 prof->GetY()[i] > 10.0*average) {
00419 prof->RemovePoint(i);
00420 i--;
00421 }
00422 }
00423 }
00424
00425
00426
00427 int BDProfMon::Index(int ) { const int do_not_call=0; assert(do_not_call); }