24 #include "TDirectory.h" 27 #include "TTimeStamp.h" 33 using std::ostringstream;
34 using std::istringstream;
47 string timeString(
int itim) {
49 string stim = ts.AsString(
"s");
61 TH1*& ph = ihin.second.ph;
65 for ( HistMap::value_type ihst :
sumHists ) {
66 TH1*& ph = ihst.second;
71 TH1*& ph = ihst.second;
81 if ( ihst ==
sumHists.end() )
return nullptr;
144 const Name myname =
"AdcRoiViewer::State::getChannelStatus: ";
147 cout << myname <<
"WARNING: Status not found for channel " << icha <<
endl;
156 const Name myname =
"AdcRoiViewer::State::getChannelStatus: ";
159 cout << myname <<
"WARNING: Channel not found for chansum histogram " << hnam <<
endl;
197 const string myname =
"AdcRoiViewer::ctor: ";
198 if (
m_LogLevel >=2 ) cout << myname <<
"Begin constructing tool." <<
endl;
199 string stringBuilder =
"adcStringBuilder";
203 cout << myname <<
"WARNING: AdcChannelStringTool not found: " << stringBuilder <<
endl;
210 cout << myname <<
"Found run data tool." <<
endl;
218 cout << myname <<
"Found tick offset tool." <<
endl;
226 cout << myname <<
"Found channel range tool." <<
endl;
237 string stimepre =
"Time since " + timeString(
m_StartTime) +
" ";
241 if ( hvarx ==
"timingPhase_fitToffPulserMod10" ) {
242 hvarx =
"fitToffPulserMod10";
243 hvary =
"timingPhase";
245 if ( hvarx ==
"event_fitToffPulser" ) {
246 hvarx =
"fitToffPulser";
254 cout << myname <<
"ERROR: Duplicate summary template name: " << hnam <<
endl;
257 int nbin = psh.get<
int>(
"nbin");
258 float xmin = psh.get<
float>(
"xmin");
259 float xmax = psh.get<
float>(
"xmax");
261 psh.get_if_present(
"fit", sfit);
263 psh.get_if_present(
"plot", plotName);
264 float plotWidth = 0.0;
265 psh.get_if_present(
"pwid", plotWidth);
267 if ( hvarx ==
"fitHeight" ) xlab =
"Fit height% [SUNIT]%";
268 else if ( hvarx ==
"fitHeightNeg" ) xlab =
"-(Fit height)% [SUNIT]%";
269 else if ( hvarx ==
"fitHeightGain" ) {
270 xlab =
"Fit height gain% [SUNIT]%";
273 if ( sden.find(
" ") != string::npos ) sden =
"(" + sden +
")";
274 xlab =
"Fit height gain [%((SUNIT))%/" + sden +
"]";
277 else if ( hvarx ==
"fitWidth" ) xlab =
"Fit width [Tick]";
278 else if ( hvarx ==
"fitPos" ) xlab =
"Fit position [Tick]";
279 else if ( hvarx ==
"fitPosRem" ) xlab =
"Fit position tick remainder [Tick]";
280 else if ( hvarx ==
"fitPosPulser" )
281 xlab =
"Fit position wrt pulser [Tick]";
282 else if ( hvarx ==
"fitToffPulser" )
283 xlab =
"Offset fit position wrt pulser [Tick]";
284 else if ( hvarx ==
"fitToffPulserMod10" )
285 xlab =
"mod_{10}(offset fit position wrt pulser) [Tick]";
286 else if ( hvarx ==
"fitChiSquare" ) xlab =
"Fit #chi^{2}";
287 else if ( hvarx ==
"fitChiSquareDof" ) xlab =
"Fit #chi^{2}/DOF";
288 else if ( hvarx ==
"fitCSNorm" ) xlab =
"Normalized fit #chi^{2}";
289 else if ( hvarx ==
"fitCSNormDof" ) xlab =
"Normalized fit #chi^{2}/DOF";
290 else if ( hvarx ==
"sigArea" ) xlab =
"Area [%ASUNIT%]";
291 else if ( hvarx ==
"sigAreaNeg" ) xlab =
"-Area [%ASUNIT%]";
292 else if ( hvarx ==
"sigWidth" ) xlab =
"Width [Tick]";
293 else if ( hvarx ==
"timeSec" || hvarx ==
"procTimeSec" ) xlab = stimepre +
" [sec]";
294 else if ( hvarx ==
"timeHour" || hvarx ==
"procTimeHour") xlab = stimepre +
" [hour]";
295 else if ( hvarx ==
"timeDay" || hvarx ==
"procTimeDay" ) xlab = stimepre +
" [day]";
297 cout << myname <<
"WARNING: Unknown summary variable: " << hvarx <<
endl;
300 if ( hvary.size() ) {
301 if ( hvary ==
"timingPhase" ) ylab =
"Timing phase [Tick]";
302 if ( hvary ==
"event" ) ylab =
"Event";
306 ph =
new TH1F(hnam.c_str(), httl.c_str(), nbin, xmin, xmax);
307 ph->GetYaxis()->SetTitle(
"# ROI");
310 int nbiny = psh.get<
int>(
"nbiny");
311 float ymin = psh.get<
float>(
"ymin");
312 float ymax = psh.get<
float>(
"ymax");
313 ph =
new TH2F(hnam.c_str(), httl.c_str(), nbin, xmin, xmax, nbiny, ymin, ymax);
314 ph->GetYaxis()->SetTitle(ylab.c_str());
316 ph->SetDirectory(
nullptr);
318 ph->GetXaxis()->SetTitle(xlab.c_str());
339 Name httl0 = psh.get<
Name>(
"title");
340 Name vhnam = psh.get<
Name>(
"valHist");
341 Name valType = psh.get<
Name>(
"valType");
342 Name etype = psh.get<
Name>(
"errType");
344 Name plname = psh.get<
Name>(
"plot");
347 if ( hnam0.size() == 0 ) {
348 cout << myname <<
"ERROR: Channel summary histogram name is missing." <<
endl;
352 cout << myname <<
"ERROR: Channel range tool not found." <<
endl;
356 if ( ivh ==
getState().sumHistTemplates.end() || ivh->second.ph == nullptr ) {
357 cout << myname <<
"ERROR: Channel summary histogram value histogram not found: " << vhnam <<
endl;
360 const NameVector valTypes = {
"entries",
"count",
"mean",
"peak",
"rms",
"sum",
"fitMean",
"fitSigma"};
361 if ( std::find(valTypes.begin(), valTypes.end(), valType) == valTypes.end() ) {
362 cout << myname <<
"ERROR: Channel summary histogram has invalid variable type: " << valType <<
endl;
365 const NameVector errTypes = {
"none",
"zero",
"rms",
"meanError",
"rmsError",
"fitSigma"};
366 if ( std::find(errTypes.begin(), errTypes.end(), etype) == errTypes.end() ) {
367 cout << myname <<
"ERROR: Channel summary histogram has invalid error type: \"" << etype <<
'"' <<
endl;
370 TH1* phval = ivh->second.ph;
371 Name valLabel = phval->GetXaxis()->GetTitle();
372 Name yttl =
"Unknown";
373 if ( valType ==
"mean" ) {
374 yttl =
"Mean of " + valLabel;
375 }
else if ( valType ==
"peak" ) {
376 yttl =
"Peak of " + valLabel;
377 }
else if ( valType ==
"rms" ) {
378 yttl =
"Sum of " + valLabel;
379 }
else if ( valType ==
"rms" ) {
380 yttl =
"RMS of " + valLabel;
381 }
else if ( valType ==
"fitMean" ) {
382 yttl =
"Fit mean of " + valLabel;
383 }
else if ( valType ==
"fitSigma" ) {
384 yttl =
"Fit sigma of " + valLabel;
385 }
else if ( valType ==
"entries" ) {
387 }
else if ( valType ==
"count" ) {
391 bool havePlotYMin =
false;
392 bool havePlotYMax =
false;
396 if ( spran.size() ) {
397 Name::size_type ipos = spran.find(
":");
398 if ( ipos == Name::npos ) {
399 cout << myname <<
"WARNING: Channel summary range specifcation must include \":\"" <<
endl;
401 Name::size_type jpos = spran.find(
":", ipos+1);
402 Name spmin = spran.substr(0, ipos);
403 if ( spmin.size() ) {
404 istringstream ssin(spmin);
408 Name spmax = spran.substr(ipos+1, jpos-ipos);
409 if ( spmax.size() ) {
410 istringstream ssin(spmax);
414 if ( jpos != Name::npos ) {
415 plotYOpt = spran.substr(jpos+1);
422 else crns.push_back(crname0);
423 if ( crns.size() == 0 ) crns.push_back(
"all");
424 for (
Name crname : crns ) {
425 if (
m_LogLevel >= 2 ) cout << myname <<
"Creating channel summary histograms for channel range " 429 cout << myname <<
"ERROR: Channel range " << crname <<
" not found." <<
endl;
439 cout << myname <<
"ERROR: Duplicate channel summary histogram name: " << hnam <<
endl;
452 phf =
new TH1F(hnam.c_str(), httl.c_str(), cr.
size(), cr.
begin, cr.
end);
453 phf->GetXaxis()->SetTitle(
"Channel");
454 phf->GetYaxis()->SetTitle(yttl.c_str());
456 phf =
new TH1F(hnam.c_str(), httl.c_str(),
nbins, plotYMin, plotYMax);
457 phf->GetXaxis()->SetTitle(yttl.c_str());
458 phf->GetYaxis()->SetTitle(
"# channels");
459 phf->SetLineWidth(2);
461 phf->SetDirectory(
nullptr);
463 if ( cr.
size() < 400 ) phf->SetLineWidth(2);
464 if ( etype ==
"none" ) phf->SetMarkerStyle(2);
465 else phf->SetMarkerStyle(0);
467 smplt.
replace(
"%HNAME%", hnam0);
472 plname = smplt.
str();
486 cout << myname <<
" Histogram name: " << hnam <<
endl;
487 cout << myname <<
" Value type: " << valType <<
endl;
488 cout << myname <<
" Error type: " << etype <<
endl;
489 cout << myname <<
" Histogram name: " << hnam <<
endl;
490 cout << myname <<
" Histogram name: " << hnam <<
endl;
491 cout << myname <<
" Plot name: " << plname <<
endl;
492 cout << myname <<
" Plot ymin: ";
493 if ( havePlotYMin ) cout << plotYMin;
495 cout << myname <<
" Plot ymax: ";
496 if ( havePlotYMax ) cout << plotYMax;
498 cout <<
" Plot yopt: " << plotYOpt <<
endl;
518 cout << myname <<
" SumNegate: " << (
m_SumNegate ?
"true" :
"false") << endl;
521 cout << myname <<
" ChannelRanges: [";
524 if ( first ) first =
false;
530 cout << myname <<
" ChannelLinePattern: {";
533 if ( ! first ) cout <<
", ";
542 cout << myname <<
" No summary histograms" <<
endl;
544 cout << myname <<
" SumHists:" <<
endl;
547 cout << myname <<
" ";
548 cout << hin.
ph->GetName() <<
"(" << hin.
varx;
549 if ( hin.
vary.size() ) cout <<
"," << hin.
vary;
557 cout << myname <<
" No channel summary histograms" <<
endl;
559 cout << myname <<
" ChanSumHists:" <<
endl;
561 TH1* ph = ihst.second;
562 cout << myname <<
" " << ph->GetName() <<
endl;
565 cout << myname <<
" PlotLabels: [";
568 if ( first ) first =
false;
573 cout << myname <<
" RunDataTool: \"" <<
m_RunDataTool <<
"\" @ " 578 if (
m_LogLevel >=2 ) cout << myname <<
"End constructing tool." <<
endl;
584 const string myname =
"AdcRoiViewer::dtor: ";
602 const string myname =
"AdcRoiViewer::viewMap: ";
609 Index ndm = save ? acds.size() : 1;
611 Index nacd = acds.size();
614 Index nroiLimit = save ? 1000 : 1000;
615 Index nroiCached = 0;
616 for (
const AdcChannelDataMap::value_type& iacd : acds ) {
619 cout << myname <<
"Processing channel " << acd.
channel()
620 <<
" (" << ncha <<
"/" << nacd <<
")" <<
endl;
627 failedChannels.push_back(acd.
channel());
630 nroi += dm.
getInt(
"roiCount");
631 nroiCached += dm.
getInt(
"roiCount");
632 if ( nroiCached > nroiLimit ) {
633 if (
m_LogLevel >= 3 ) cout << myname <<
" Clearing result cache." <<
endl;
640 ret.
setInt(
"roiChannelCount", ncha);
641 ret.
setInt(
"roiFailedChannelCount", nfail);
643 ret.
setInt(
"roiCount", nroi);
650 const string myname =
"AdcRoiViewer::close: ";
655 cout << myname <<
"Closing." <<
endl;
662 if (
m_LogLevel >= 2 ) cout << myname <<
"Printing " << ntpm <<
" ROI pad" 663 << (ntpm == 1 ?
"" :
"s") <<
endl;
665 Index icha = itpm.first;
666 TpmPtr& pmantop = itpm.second;
669 if (
m_LogLevel >=3 ) cout << myname <<
"Writing " << plotFileName <<
endl;
670 pmantop->print(plotFileName);
671 pmantop.
reset(
nullptr);
680 if (
getState().chanSumHists.size() ) {
691 const string myname =
"AdcRoiViewer::doView: ";
692 unsigned int ievt = acd.
event();
699 unsigned int nraw = acd.
raw.size();
700 unsigned int nsam = acd.
samples.size();
701 unsigned int ntickChannel = nsam > nraw ? nsam : nraw;
702 unsigned int nroiRaw = acd.
rois.size();
704 bool histRelativeTick =
false;
713 histRelativeTick =
true;
716 histRelativeTick =
true;
722 if ( dbg >=2 ) cout << myname <<
"Processing channel " << acd.
channel() <<
"." 723 <<
" Input ROI count is " << nroiRaw <<
endl;
742 for (
unsigned int iroiRaw=0; iroiRaw<nroiRaw; ++iroiRaw ) {
744 if ( dbg >=3 ) cout << myname <<
" ROI " << nroi <<
"(raw " << iroiRaw <<
"): [" 745 << roi.first <<
", " << roi.second <<
"]" <<
endl;
746 ostringstream sshnam;
747 sshnam <<
"hroi_run_%0RUN%_evt%0EVENT%_chan%0CHAN%_roi";
748 if ( nroi < 100 ) sshnam <<
"0";
749 if ( nroi < 10 ) sshnam <<
"0";
751 string hnam = AdcChannelStringTool::AdcChannelStringTool::build(
m_adcStringBuilder, acd, sshnam.str());
752 ostringstream sshttl;
753 sshttl <<
"Run %RUN% event %EVENT% channel %CHAN% ROI " << nroi;
754 sshttl <<
" ;Tick ;";
755 if ( histType == 1 ) sshttl <<
"Signal% [SUNIT]%";
756 if ( histType == 2 ) sshttl <<
"ADC count";
758 unsigned int isam1 = roi.first;
759 unsigned int isam2 = roi.second + 1;
765 float x1 = histRelativeTick ? 0.0 : isam1;
766 float x2 = histRelativeTick ? isam2 - isam1 : isam2;
767 TH1* ph =
new TH1F(hnam.c_str(), httl.c_str(), isam2-isam1,
x1,
x2);
768 ph->SetDirectory(
nullptr);
772 unsigned int ibin = 0;
780 for (
unsigned int isam=isam1; isam<isam2; ++isam ) {
782 if ( histType == 1 && isam<nsam ) sig = acd.
samples[isam];
783 if ( histType == 2 && isam<nraw ) sig = isam<nraw ? acd.
raw[isam] : 0.0;
788 if ( sig < sigmin ) {
792 if ( sig > sigmax ) {
798 ph->SetBinContent(++ibin, sig);
804 if ( m_SigThresh < 0.0 && sigmin >
m_SigThresh )
continue;
805 if ( m_SigThresh > 0.0 && sigmax < m_SigThresh )
continue;
807 roiHists.push_back(ph);
808 roiTickMins.push_back(roiTickMin);
809 roiNUnderflows.push_back(nunder);
810 roiNOverflows.push_back(nover);
811 roiTickMaxs.push_back(roiTickMax);
813 roiSigMins.push_back(sigmin);
814 roiSigMaxs.push_back(sigmax);
815 roiSigAreas.push_back(sigarea);
816 tick1.push_back(isam1);
817 ntick.push_back(isam2 - isam1);
819 if ( dbg >= 3 ) cout <<
" Fitting with coldelecResponse" <<
endl;
820 bool isNeg = fabs(sigmin) > sigmax;
821 double h = isNeg ? sigmin : sigmax;
823 double shap = 0.8*fabs(sigarea)/fabs(h);
824 double t0 = x1 + (isNeg ? roiTickMin : roiTickMax) - shap;
829 pfinit->SetLineColor(3);
830 pfinit->SetLineStyle(2);
834 if ( dbg < 3 ) fopt +=
"Q";
838 xshift = 500*(long(t0)/500);
840 int fstat =
shiftHistFit(ph, pf, fopt.c_str(), 2, xshift);
841 ph->GetListOfFunctions()->AddLast(pfinit,
"0");
842 ph->GetListOfFunctions()->Last()->SetBit(TF1::kNotDraw,
true);
843 ph->GetListOfFunctions()->SetOwner(kTRUE);
844 roiFitHeights.push_back(pf->GetParameter(0));
845 roiFitWidths.push_back(pf->GetParameter(1));
846 roiFitPositions.push_back(pf->GetParameter(2));
847 roiFitStats.push_back(fstat);
848 float cs = pf->GetChisquare();
849 int ndf = pf->GetNDF();
850 float csn = ndf > 0 ? cs/
float(ndf) : -1.0;
851 roiFitChiSquares.push_back(cs);
852 roiFitChiSquareDofs.push_back(csn);
862 res.
setInt(
"roiCount", nroi);
863 res.
setInt(
"roiRawCount", nroiRaw);
864 res.
setInt(
"roiNTickChannel", ntickChannel);
876 if ( roiFitHeights.size() ) {
896 if (
getState().cachedSampleUnit.size() == 0 ) {
913 const string myname =
"AdcRoiViewer::writeRoiHists: ";
915 TDirectory* savdir = gDirectory;
916 string ofrnameOld =
"";
917 TFile* pfile =
nullptr;
918 for (
const DataMap& dm : dms ) {
922 dm.getInt(
"roiEvent"),
923 dm.getInt(
"roiSubRun")
927 if ( ofrname != ofrnameOld ) {
928 if ( pfile !=
nullptr ) pfile->Close();
930 if (
m_LogLevel >= 2 ) cout << myname <<
"Writing histograms to " << ofrname <<
endl;
931 pfile = TFile::Open(ofrname.c_str(),
"UPDATE");
932 ofrnameOld = ofrname;
935 for ( TH1* ph : roiHists ) {
936 TH1* phnew =
dynamic_cast<TH1*
>(ph->Clone());
937 phnew->GetListOfFunctions()->SetOwner(kTRUE);
939 if ( dbg >= 3 ) cout << myname <<
" Wrote " << phnew->GetName() <<
endl;
942 if ( pfile !=
nullptr ) pfile->Close();
950 const string myname =
"AdcRoiViewer::writeRoiPlots: ";
954 Index npad = npadx*npady;
955 if ( npad == 0 )
return;
966 if ( pmantop && npad > 1 ) {
967 for ( ipad=0; ipad<npad; ++ipad ) {
968 if ( pmantop->man(ipad)->hist() == nullptr )
break;
970 if ( ipad >= npad ) {
971 cout << myname <<
"FATAL: ROI pad is full." <<
endl;
977 for ( TH1* ph : hsts ) {
978 if ( ph ==
nullptr )
continue;
979 Name hnam = ph->GetName();
981 plotFileName = hnam.substr(1) +
".png";
985 string scha = sscha.str();
986 while ( scha.size() < 6 ) scha =
"0" + scha;
989 string spag = sspag.str();
990 while ( spag.size() < 3 ) spag =
"0" + spag;
991 plotFileName =
"roi_chan" + scha +
"_" + spag +
".png";
996 pmantop->setCanvasSize(wpadx, wpady);
997 if ( npad > 1 ) pmantop->split(npadx, npady);
998 if (
m_LogLevel >= 3 ) cout << myname <<
" Creating plots for " << plotFileName <<
endl;
999 if (
m_LogLevel >= 4 ) cout << myname <<
" Plotting " << ph->GetName() <<
endl;
1002 pman->
add(ph,
"hist",
false);
1004 TF1* pfit = ph->GetFunction(
"coldelec");
1007 double area = ph->Integral();
1008 ostringstream ssout;
1010 ssout.setf(std::ios_base::fixed);
1011 ssout <<
"Area: " << area;
1012 labs.push_back(ssout.str());
1013 if ( pfit !=
nullptr ) {
1014 double height = pfit->GetParameter(
"Height");
1015 double shaping = pfit->GetParameter(
"Shaping");
1016 double t0 = pfit->GetParameter(
"T0");
1018 ssout <<
"Height: " << height;
1019 labs.push_back(ssout.str());
1021 ssout <<
"Shaping: " << shaping <<
" tick";
1022 labs.push_back(ssout.str());
1025 ssout <<
"Position: " << t0 <<
" tick";
1026 labs.push_back(ssout.str());
1029 ssout <<
"#chi^{2}: " << pfit->GetChisquare();
1030 labs.push_back(ssout.str());
1037 double dylab = 0.04;
1038 for (
Name lab : labs ) {
1039 TLatex* pptl =
nullptr;
1040 pptl =
new TLatex(xlab, ylab, lab.c_str());
1042 pptl->SetTextFont(42);
1043 pptl->SetTextSize(dylab);
1053 if ( ipad >= npad || (++ihst >= hsts.size() &&
m_RoiPlotOpt != 2) ) {
1054 if (
m_LogLevel >= 3 ) cout << myname <<
" Writing " << plotFileName <<
endl;
1055 pmantop->print(plotFileName);
1056 pmantop.
reset(
nullptr);
1068 const string myname =
"AdcRoiViewer::fillSumHists: ";
1075 if (
m_LogLevel >= 2 ) cout << myname <<
"Setting run data." <<
endl;
1078 if ( rdat.
run() != rdatOld.
run() ) {
1079 cout << myname <<
"Ignoring unexpected change in run number: " << rdatOld.
run()
1080 <<
" --> " << rdat.
run();
1082 }
else if ( ! rdat.
isValid() ) {
1083 if (
m_LogLevel >= 3 ) cout << myname <<
"Run data not found." <<
endl;
1086 float pulserQin = 0.0;
1089 bool haveQin =
false;
1090 if ( havePulserAmplitude ) {
1094 haveQin = pulserQin != 0.0;
1096 cout << myname <<
"WARNING: Pulser charge evaluates to zero." <<
endl;
1099 Index pulserPeriod = 0;
1100 if ( havePulserPeriod ) {
1102 if ( pulserPeriod == 0 ) {
1103 havePulserPeriod =
false;
1104 cout << myname <<
"WARNING: Pulser period is zero." <<
endl;
1109 bool haveTickOffset =
false;
1110 long tickOffset = 0;
1111 bool haveTickOffsetPulserMod =
false;
1112 Index tickOffsetPulserMod = 0;
1113 double timingPhase = 0.0;
1123 haveTickOffset =
true;
1124 tickOffset = off.
value;
1125 timingPhase = off.
rem;
1127 cout << myname <<
"Unable to retrieve tick offset for run " << tdat.
run <<
"-" << tdat.
subrun 1130 if ( haveTickOffset && havePulserPeriod ) {
1131 long toff = tickOffset;
1132 long period = pulserPeriod;
1133 toff = toff % period;
1134 if ( toff < 0 ) toff += period;
1135 tickOffsetPulserMod = toff;
1136 haveTickOffsetPulserMod =
true;
1147 if ( varx ==
"fitHeight" ) varx =
"fitHeightNeg";
1148 if ( varx ==
"sigArea" ) varx =
"sigAreaNeg";
1156 if ( varx ==
"sigArea" ) vals = dm.
getFloatVector(
"roiSigAreas");
1157 else if ( varx ==
"sigAreaNeg" ) vals = dm.
getFloatVector(
"roiSigAreas");
1158 else if ( varx ==
"sigWidth" ) ivals = dm.
getIntVector(
"roiNTicks");
1159 else if ( varx ==
"sigTick0" ) ivals = dm.
getIntVector(
"roiTick0s");
1160 else if ( varx ==
"sigTick0Pulser" ) ivals = dm.
getIntVector(
"roiTick0s");
1161 else if ( varx ==
"sigTickMax" ) ivals = dm.
getIntVector(
"roiTickMaxs");
1162 else if ( varx ==
"sigTickMaxPulser" ) ivals = dm.
getIntVector(
"roiTickMaxs");
1163 else if ( varx ==
"fitHeight" ) vals = dm.
getFloatVector(
"roiFitHeights");
1164 else if ( varx ==
"fitHeightNeg" ) vals = dm.
getFloatVector(
"roiFitHeights");
1165 else if ( varx ==
"fitHeightGain" ) vals = dm.
getFloatVector(
"roiFitHeights");
1166 else if ( varx ==
"fitWidth" ) vals = dm.
getFloatVector(
"roiFitWidths");
1167 else if ( varx ==
"fitPos" ) vals = dm.
getFloatVector(
"roiFitPositions");
1168 else if ( varx ==
"fitPosRem" ) vals = dm.
getFloatVector(
"roiFitPositions");
1169 else if ( varx ==
"fitPosPulser" ) vals = dm.
getFloatVector(
"roiFitPositions");
1170 else if ( varx ==
"fitToffPulser" ) vals = dm.
getFloatVector(
"roiFitPositions");
1171 else if ( varx ==
"fitToffPulserMod10" ) vals = dm.
getFloatVector(
"roiFitPositions");
1172 else if ( varx ==
"fitStat" ) ivals = dm.
getIntVector(
"roiFitStats");
1173 else if ( varx ==
"fitChiSquare" ) vals = dm.
getFloatVector(
"roiFitChiSquares");
1174 else if ( varx ==
"fitChiSquareDof" ) vals = dm.
getFloatVector(
"roiFitChiSquareDofs");
1175 else if ( varx ==
"fitCSNorm" ) vals = dm.
getFloatVector(
"roiFitChiSquares");
1176 else if ( varx ==
"fitCSNormDof" ) vals = dm.
getFloatVector(
"roiFitChiSquareDofs");
1177 else if ( varx ==
"timeSec" ) ivals = dm.
getIntVector(
"roiTimes");
1178 else if ( varx ==
"timeHour" ) ivals = dm.
getIntVector(
"roiTimes");
1179 else if ( varx ==
"timeDay" ) ivals = dm.
getIntVector(
"roiTimes");
1180 else if ( varx ==
"procEvent" ) ivals.push_back(acd.
event());
1181 else if ( varx ==
"procTimeSec" ) ivals.push_back(
int(acd.
time()) -
int(
m_StartTime));
1182 else if ( varx ==
"procTimeHour" ) ivals.push_back(
int(acd.
time()) -
int(
m_StartTime));
1183 else if ( varx ==
"procTimeDay" ) ivals.push_back(
int(acd.
time()) -
int(
m_StartTime));
1186 cout << myname <<
"ERROR: Invalid variable name: " << varx <<
endl;
1190 Name hnam0 = ph0->GetName();
1193 Name ylab = ph0->GetYaxis()->GetTitle();
1195 if ( ivals.size() && !vals.size() )
for (
int ival : ivals ) vals.push_back(ival);
1196 if ( varx ==
"fitPosRem" )
for (
float&
val : vals )
val = std::remainder(
val,1);
1197 if ( varx ==
"fitPosPulser" ) {
1198 if ( ! havePulserPeriod ) {
1199 cout << myname <<
"WARNING: Cannot evaluate " << varx <<
" without pulser period" <<
endl;
1202 for (
float&
val : vals )
val = fmod(
val, pulserPeriod);
1204 if ( varx ==
"fitToffPulser" || varx ==
"fitToffPulserMod10" ||
1205 varx ==
"sigTick0Pulser" || varx ==
"sigTickMaxPulser" ) {
1206 if ( ! haveTickOffsetPulserMod ) {
1207 cout << myname <<
"WARNING: Cannot evaluate " << varx <<
" without timing offset and pulser period" <<
endl;
1210 for (
float&
val : vals )
val = fmod(
val + pulserPeriod + tickOffsetPulserMod, pulserPeriod);
1211 if ( varx ==
"fitToffPulserMod10" ) {
1212 for (
float&
val : vals )
val = fmod(
val, 10.0);
1216 if ( varx ==
"fitHeightNeg" ) varfac = -1.0;
1217 if ( varx ==
"sigAreaNeg" ) varfac = -1.0;
1218 if ( varx ==
"fitCSNorm" || varx ==
"fitCSNormDof" ) {
1220 if ( pedrms > 0.0 ) varfac = 1.0/(pedrms*pedrms);
1223 if ( varx ==
"fitHeightGain" ) {
1225 cout << myname <<
"WARNING: Cannot evaluate " << varx <<
" without Qin" <<
endl;
1228 varfac = 1.0/pulserQin;
1230 if ( varx ==
"timeHour" || varx ==
"procTimeHour" ) varfac = 1/3600.0;
1231 if ( varx ==
"timeDay" || varx ==
"procTimeDay" ) varfac = 1/(24*3600.0);
1232 if ( varfac != 1.0 )
for (
float&
val : vals )
val *= varfac;
1236 if ( (ph ==
nullptr) || (ph->GetEntries() == 0 && vals.size()) ) {
1237 bool replacingHistogram = ph !=
nullptr;
1241 bool havePlot = plotNameTemplate.size();
1244 if ( replacingHistogram ) {
1246 iplotHist = find(plotHists.begin(), plotHists.end(), ph);
1247 if ( iplotHist == plotHists.end() ) {
1248 cout << myname <<
"ERROR: Unable to find histogram in plot name list." <<
endl;
1250 iplotHist = plotHists.end();
1252 *iplotHist =
nullptr;
1256 if (
m_LogLevel >= 2 ) cout << myname <<
"Replacing histogram " << hnam <<
endl;
1259 plotHists.push_back(
nullptr);
1260 iplotHist = plotHists.end();
1263 if (
m_LogLevel >= 2 ) cout << myname <<
"Creating histogram " << hnam <<
endl;
1265 Name httl0 = ph0->GetTitle();
1267 int nbin = ph0->GetNbinsX();
1268 float xmin = ph0->GetXaxis()->GetXmin();
1269 float xmax = ph0->GetXaxis()->GetXmax();
1272 if ( vals.size() && xmin > xmax && xmin > 0.0 ) {
1274 std::sort(tmpvals.begin(), tmpvals.end());
1275 Index nval = tmpvals.size();
1276 if (
m_LogLevel >= 3 ) cout << myname <<
" Centering histogram on median of " 1277 << nval <<
" value" << (nval==1 ?
"" :
"s") <<
endl;
1278 float xmed = 0.5*(tmpvals[(nval-1)/2] + tmpvals[nval/2]);
1280 xmin = xmed - 0.5*width;
1281 bool roundXmin = xmax > 0.0;
1287 xmin = rfac*
int(xmin/rfac + (xmin > 0.0 ? 0.5 : -0.5));
1289 xmax = xmin + width;
1291 }
else if ( xmin >= xmax ) {
1295 }
else if ( xmin < 0.0 ) {
1303 cout << myname <<
" Name: " << hnam <<
endl;
1304 cout << myname <<
" Title: " << httl <<
endl;
1305 cout << myname <<
" nbin: " << nbin <<
endl;
1306 cout << myname <<
" xmin: " << xmin <<
endl;
1307 cout << myname <<
" xmax: " << xmax <<
endl;
1308 cout << myname <<
" fit: " << fitName <<
endl;
1310 bool isTH2 =
dynamic_cast<TH2*
>(ph0);
1312 ph =
new TH1F(hnam.c_str(), httl.c_str(), nbin, xmin, xmax);
1314 int nbiny = ph0->GetNbinsY();
1315 float ymin = ph0->GetYaxis()->GetXmin();
1316 float ymax = ph0->GetYaxis()->GetXmax();
1317 ph =
new TH2F(hnam.c_str(), httl.c_str(), nbin, xmin, xmax, nbiny, ymin, ymax);
1319 ph->SetDirectory(
nullptr);
1322 ph->SetLineWidth(2);
1323 ph->GetXaxis()->SetTitle(xlab.c_str());
1324 ph->GetYaxis()->SetTitle(ylab.c_str());
1325 if ( ph0->GetListOfFunctions()->GetEntries() ) {
1326 TF1* pf =
dynamic_cast<TF1*
>(ph0->GetListOfFunctions()->At(0)->Clone());
1327 ph->GetListOfFunctions()->AddLast(pf);
1328 ph->GetListOfFunctions()->SetOwner(kTRUE);
1333 if ( plotNameTemplate.size() ) {
1335 if ( havePlot ) *iplotHist = ph;
1336 if ( ! replacingHistogram ) {
1342 if (
m_LogLevel >= 3 ) cout << myname <<
"Filling summary histogram " << hnam
1343 <<
". Fill count is " << vals.size() <<
endl;
1346 bool checkFit = varx.substr(0,3) ==
"fit";
1347 if ( csds.size() == 0 || fstats.size() == 0 ) checkFit =
false;
1348 double chiSquareDofMax = 0.0;
1350 if ( csds.size() != vals.size() ) {
1351 cout <<
"ERROR: Variable and chi-square/DF vectors have different sizes." <<
endl;
1354 if ( fstats.size() != vals.size() ) {
1355 cout <<
"ERROR: Variable and fit status vectors have different sizes: " 1356 << vals.size() <<
" != " << fstats.size() <<
endl;
1362 bool logerr =
m_LogLevel >= 3 && nhstGood == 0;
1363 for (
Index ival=0; ival<vals.size(); ++ival ) {
1366 int fstat = fstats[ival];
1367 float csd = csds[ival];
1369 if ( logerr) cout << myname <<
"WARNING: Skipping entry with fit status " << fstat
1370 <<
" (chi-square/DOF = " << csd <<
")" <<
endl;
1373 }
else if ( chiSquareDofMax > 0.0 && csd > chiSquareDofMax ) {
1374 if ( logerr) cout << myname <<
"WARNING: Skipping entry with chi-square/DOF = " << csd <<
endl;
1379 float val = vals[ival];
1381 if ( vary ==
"timingPhase" ) valy = timingPhase;
1382 if ( vary ==
"event" ) valy = acd.
event();
1386 ph->Fill(val, valy);
1391 cout << myname <<
"WARNING: Skipped " << nvalSkip <<
" of " << nval
1392 <<
" entries due to bad fit for histogram " << hnam <<
"." <<
endl;
1396 if ( nhstGood != nhst ) {
1397 cout << myname <<
"WARNING: Only filled " << nhstGood <<
" of " << nhst <<
" histograms." <<
endl;
1404 const string myname =
"AdcRoiViewer::fitSumHists: ";
1405 if (
getState().sumHists.size() == 0 ) {
1406 cout << myname <<
"No summary histograms found." <<
endl;
1409 if (
m_LogLevel >= 1 ) cout << myname <<
"Fitting summary histograms. Count is " 1411 for ( HistMap::value_type ihst :
getState().sumHists ) {
1412 TH1* ph = ihst.second;
1413 string hnam = ph->GetName();
1415 bool fitDone =
false;
1416 if (
m_LogLevel >= 3 ) cout << myname <<
"Fitting hist " << ph->GetName() <<
" with " << fitName <<
endl;
1417 if ( fitName.size() ) {
1419 int binMax = ph->GetMaximumBin();
1420 double mean0 = ph->GetBinLowEdge(binMax);
1421 double sigma0 = ph->GetRMS();
1422 double height0 = ph->GetMaximum();
1424 if ( fitName.substr(0,5) ==
"sgaus" ) {
1425 if (
m_LogLevel >= 4 ) cout << myname <<
" Doing gaus step fit." <<
endl;
1426 if ( fitName.size() > 5 ) {
1427 istringstream ssin(fitName.substr(5));
1431 fitDone = gsf.
fit(ph) == 0;
1433 }
else if ( fitName.substr(0,5) ==
"rgaus" ) {
1434 if (
m_LogLevel >= 4 ) cout << myname <<
" Doing fixed rms fit." <<
endl;
1435 double sigma0 = 0.0;
1436 double nsigma = 4.0;
1437 Name spar1 = fitName.substr(5);
1439 if ( spar1.size() ) {
1440 if ( spar1[0] ==
'_' ) spar1 = spar1.substr(1);
1441 string::size_type ipos = spar1.find(
"_");
1442 if ( ipos != string::npos ) {
1443 spar2 = spar1.substr(ipos+1);
1444 spar1 = spar1.substr(0, ipos);
1445 istringstream ssin2(spar2);
1448 istringstream ssin1(spar1);
1453 if ( grf.
fit(ph, mean0) == 0 ) {
1456 pf =
new TF1(
"mygaus",
"gaus");
1459 pf =
new TF1(fitName.c_str(), fitName.c_str());
1462 cout << myname <<
" Created function " << pf->GetName() <<
" at " <<
std::hex << pf <<
endl;
1465 if (
m_LogLevel >= 4 ) cout << myname <<
" Doing unconstrained fit" <<
endl;
1466 string fopt =
"LWWS";
1470 cout << myname <<
" WARNING: Fit " << pf->GetName() <<
" of " << ph->GetName() <<
" returned " << fstat <<
endl;
1471 ph->GetListOfFunctions()->Clear();
1473 if (
m_LogLevel >=4 ) cout << myname <<
" Fit succeeded." <<
endl;
1475 ph->GetListOfFunctions()->SetOwner(kTRUE);
1485 const string myname =
"AdcRoiViewer::writeSumHists: ";
1487 if ( ! saveHist )
return;
1488 if (
getState().sumHists.size() == 0 ) {
1489 cout << myname <<
"No summary histograms found." <<
endl;
1492 TDirectory* savdir = gDirectory;
1494 TFile* pfile = TFile::Open(ofrname.c_str(),
"UPDATE");
1495 saveHist = pfile !=
nullptr && pfile->IsOpen();
1497 cout << myname <<
"ERROR: Unable to open output file " << ofrname <<
endl;
1500 if (
m_LogLevel >= 1 ) cout << myname <<
"Writing summary histograms. Count is " 1502 for ( HistMap::value_type ihst :
getState().sumHists ) {
1503 TH1* ph = ihst.second;
1504 TH1* phnew =
dynamic_cast<TH1*
>(ph->Clone());
1505 if ( saveHist ) phnew->Write();
1506 if (
m_LogLevel >= 2 ) cout << myname <<
" Wrote " << phnew->GetName() <<
endl;
1509 if (
m_LogLevel >= 1 ) cout << myname <<
"Closed summary histogram file " << ofrname <<
endl;
1517 const string myname =
"AdcRoiViewer::writeSumPlots: ";
1518 int dbgin = pdmin ==
nullptr ? 0 : pdmin->
getInt(
"dbg", 0);
1526 if ( npad == 0 )
return;
1527 if (
m_LogLevel >= 1 ) cout << myname <<
"Plotting " << nvec <<
" set" 1528 << (nvec == 1 ?
"" :
"s") <<
" of summary histograms " <<
endl;
1530 Name plotNameTemplate = ihv.first;
1535 for (
Index ihst=0; ihst<hsts.size(); ++ihst ) {
1536 TH1* ph = hsts[ihst];
1537 if ( ph ==
nullptr ) {
1538 cout << myname <<
"WARNING: Histogram " << ihst <<
" not found for template " << plotNameTemplate <<
endl;
1540 Name hnam = ph->GetName();
1541 bool haveExpectedValue = pdmin !=
nullptr && pdmin->
haveFloat(hnam);
1542 float expValue = haveExpectedValue ? pdmin->
getFloat(hnam) : 0.0;
1544 cout << myname <<
" Processing histogram " << hnam <<
endl;
1545 if ( haveExpectedValue ) cout << myname <<
" Expected value: " << expValue <<
endl;
1546 else cout << myname <<
" No expected value." <<
endl;
1548 if ( pmantop ==
nullptr ) {
1550 if ( plotFileName.size() == 0 ) {
1551 cout << myname <<
"ERROR: Plot file name is not assigned for " << hnam <<
endl;
1557 if ( npad > 1 ) pmantop->
split(npadx, npady);
1558 if (
m_LogLevel >= 2 ) cout << myname <<
" Creating plots for " << plotFileName <<
endl;
1560 if (
m_LogLevel >= 3 ) cout << myname <<
" Plotting " << ph->GetName() <<
endl;
1562 pman->
add(ph,
"hist",
false);
1563 if ( ph->GetListOfFunctions()->GetEntries() ) {
1571 if ( plotWidth > 0.0 ) {
1572 int binMax = ph->GetMaximumBin();
1573 if ( binMax && binMax <= ph->GetNbinsX() ) {
1574 float xCen = ph->GetBinLowEdge(binMax);
1575 float xmin = xCen - 0.5*plotWidth;
1576 float xmax = xCen + 0.5*plotWidth;
1581 bool showMean =
true;
1583 double mean = ph->GetMean();
1584 double sigm = ph->GetRMS();
1585 float meanDen = haveExpectedValue ? expValue :
mean;
1586 ostringstream ssout;
1588 ssout.setf(std::ios_base::fixed);
1590 ssout <<
"# ROI: " <<
int(ph->GetEntries() + 0.1);
1591 labs.push_back(ssout.str());
1593 ssout <<
"Hist mean: " <<
mean;
1594 labs.push_back(ssout.str());
1596 ssout <<
"Hist RMS: " << sigm;
1598 if ( meanDen != 0.0 ) ssout <<
" [" << 100*sigm/meanDen <<
"%]";
1600 labs.push_back(ssout.str());
1601 if ( haveExpectedValue ) {
1603 float bias = mean - expValue;
1604 ssout <<
"Hist bias: " << bias;
1606 if ( expValue != 0.0 ) ssout <<
" [" << 100*bias/expValue <<
"%]";
1608 labs.push_back(ssout.str());
1611 TF1* pffit =
dynamic_cast<TF1*
>(ph->GetListOfFunctions()->Last());
1612 if ( pffit !=
nullptr ) {
1613 string fnam = pffit->GetName();
1614 double mean = pffit->GetParameter(
"Mean");
1615 double sigm = pffit->GetParameter(
"Sigma");
1616 float meanDen = haveExpectedValue ? expValue :
mean;
1617 labs.push_back(
"Fitter: " + fnam);
1618 ostringstream ssout;
1620 ssout.setf(std::ios_base::fixed);
1621 ssout <<
"Fit mean: " <<
mean;
1622 labs.push_back(ssout.str());
1624 ssout <<
"Fit sigma: " << sigm;
1626 if ( meanDen != 0.0 ) ssout <<
" [" << 100*sigm/meanDen <<
"%]";
1628 labs.push_back(ssout.str());
1629 if ( haveExpectedValue ) {
1631 float bias = mean - expValue;
1632 ssout <<
"Fit bias: " << bias;
1634 if ( expValue != 0.0 ) ssout <<
" [" << 100*bias/expValue <<
"%]";
1636 labs.push_back(ssout.str());
1640 ostringstream ssout;
1648 double dylab = 0.04;
1649 for (
Name lab : labs ) {
1650 TLatex* pptl =
nullptr;
1651 pptl =
new TLatex(xlab, ylab, lab.c_str());
1653 pptl->SetTextFont(42);
1654 pptl->SetTextSize(dylab);
1660 if ( ipad >= npad || ihst+1 >= hsts.size() ) {
1661 if ( pmantop ==
nullptr ) {
1662 if (
m_LogLevel >= 2 ) cout << myname <<
" Not writing empty plot" <<
endl;
1664 if (
m_LogLevel >= 2 ) cout << myname <<
" Writing " << plotFileName <<
endl;
1665 pmantop->
print(plotFileName);
1678 const string myname =
"AdcRoiViewer::fillChanSumHists: ";
1679 if (
getState().chanSumHists.size() == 0 ) {
1680 cout << myname <<
"No channel summary histograms found." <<
endl;
1684 if (
m_LogLevel >= 1 ) cout << myname <<
"Filling channel summary histograms. Count is " 1686 for ( HistMap::value_type ihst :
getState().chanSumHists ) {
1687 TH1* ph = ihst.second;
1688 Name hnam = ph->GetName();
1690 if ( hnamTemplate.size() == 0 ) {
1691 cout << myname <<
"ERROR: Summary template histogram name not found for channel summary " << hnam <<
endl;
1696 double errmin = 0.0;
1697 if ( errtype.substr(0,3) ==
"rms" && errtype.size() > 3 ) {
1698 string serrmin = errtype.substr(3);
1699 istringstream ssermin(serrmin);
1704 if ( vartype.size() == 0 ) {
1705 cout << myname <<
"ERROR: Variable type name not found for " << hnam <<
endl;
1718 for (
Index icha=icha1; icha<icha2; ++icha ) {
1719 Index ichaBin = icha + 1 - icha1;
1726 if ( phvar ==
nullptr ) {
1728 cout << myname <<
"Unable to find sum hist " << hnam <<
endl;
1732 if ( vartype ==
"mean" ) {
1733 val = phvar->GetMean();
1734 }
else if ( vartype ==
"peak" ) {
1735 int ibin = phvar->GetMaximumBin();
1736 val = phvar->GetBinCenter(ibin);
1737 }
else if ( vartype ==
"rms" ) {
1738 val = phvar->GetRMS();
1739 }
else if ( vartype ==
"entries" ) {
1740 val = phvar->GetEntries();
1741 }
else if ( vartype ==
"count" ) {
1742 val = phvar->Integral();
1743 }
else if ( vartype ==
"sum" ) {
1744 val = phvar->Integral()*phvar->GetMean();
1745 }
else if ( vartype.substr(0,3) ==
"fit" ) {
1746 Index nfun = phvar->GetListOfFunctions()->GetEntries();
1747 TF1* pf = nfun ?
dynamic_cast<TF1*
>(phvar->GetListOfFunctions()->At(0)) :
nullptr;
1748 if ( pf ==
nullptr ) {
1750 cout << myname <<
"Unable to find find fit for sum hist " << hnam <<
endl;
1753 bool doRat = vartype.substr(3,3) ==
"rat";
1754 string::size_type ipos = doRat ? 6 : 3;
1755 Name spar = vartype.substr(ipos);
1756 int ipar = pf->GetParNumber(spar.c_str());
1759 cout << myname <<
"ERROR: Invalid fit parameter name: " << spar <<
endl;
1762 val = pf->GetParameter(ipar);
1764 double mean = pf->GetParameter(
"Mean");
1765 val *= (mean == 0.0 ? 0.0 : 1.0/
mean);
1768 cout << myname <<
"Invalid variable type " << vartype <<
" for " << hnam <<
endl;
1772 bool haveErr =
true;
1773 if ( errtype ==
"none" ) {
1775 }
else if ( errtype ==
"zero" ) {
1777 }
else if ( errtype.substr(0,3) ==
"rms" ) {
1778 dval = phvar->GetRMS();
1779 if ( dval < errmin ) dval = errmin;
1780 }
else if ( errtype ==
"meanError" ) {
1781 dval = phvar->GetMeanError();
1782 if ( dval < errmin ) dval = errmin;
1783 }
else if ( errtype ==
"rmsError" ) {
1784 dval = phvar->GetRMSError();
1785 if ( dval < errmin ) dval = errmin;
1786 }
else if ( errtype.substr(0,3) ==
"fit" ) {
1787 Index nfun = phvar->GetListOfFunctions()->GetEntries();
1788 TF1* pf = nfun ?
dynamic_cast<TF1*
>(phvar->GetListOfFunctions()->At(0)) :
nullptr;
1789 if ( phvar ==
nullptr ) {
1791 cout << myname <<
"Unable to find find fit for sum hist " << hnam <<
endl;
1794 Name spar = errtype.substr(3);
1795 int ipar = pf->GetParNumber(spar.c_str());
1797 cout << myname <<
"ERROR: Invalid fit parameter name: " << spar <<
endl;
1799 dval = pf->GetParameter(ipar);
1802 cout << myname <<
"Invalid error type: " << errtype <<
endl;
1805 if ( ph->GetEntries() == 0 ) {
1806 TAxis* paxis = isDist ? ph->GetXaxis() : ph->GetYaxis();
1807 Name vlabOld = paxis->GetTitle();
1809 if ( vlabNew != vlabOld ) {
1810 if (
m_LogLevel >= 3 ) cout << myname <<
"Setting variable label for " << hnam
1811 <<
" to \"" << vlabNew <<
"\"." <<
endl;
1812 paxis->SetTitle(vlabNew.c_str());
1814 Name httlOld = ph->GetTitle();
1816 if ( httlNew != httlOld ) {
1817 if (
m_LogLevel >= 3 ) cout << myname <<
"Setting title for " << hnam <<
" to \"" 1818 << httlNew <<
"\"." <<
endl;
1819 ph->SetTitle(httlNew.c_str());
1825 ph->SetBinContent(ichaBin, val);
1826 if ( haveErr ) ph->SetBinError(ichaBin, dval);
1830 if ( nchaGood < ncha ) {
1831 cout << myname <<
"WARNING: Only filled " << nchaGood <<
" of " << ncha
1832 <<
" channels for channel summary histogram " << hnam <<
endl;
1840 const string myname =
"AdcRoiViewer::writeChanSumHists: ";
1843 cout << myname <<
"No channel summary histograms found." <<
endl;
1847 TDirectory* savdir = gDirectory;
1848 TFile* pfile = TFile::Open(ofrname.c_str(),
"UPDATE");
1849 if (
m_LogLevel >= 1 ) cout << myname <<
"Writing channel summary histograms. Count is " 1851 for ( HistMap::value_type ihst :
getState().chanSumHists ) {
1852 TH1* ph = ihst.second;
1853 TH1* phnew =
dynamic_cast<TH1*
>(ph->Clone());
1855 if (
m_LogLevel >= 2 ) cout << myname <<
" Wrote " << phnew->GetName() <<
endl;
1857 if ( pfile !=
nullptr ) pfile->Close();
1859 if (
m_LogLevel >= 1 ) cout << myname <<
"Closed summary histogram file " << ofrname <<
endl;
1866 const string myname =
"AdcRoiViewer::writeChanSumPlots: ";
1867 for ( HistMap::value_type ihst :
getState().chanSumHists ) {
1868 TH1* ph = ihst.second;
1869 Name hnam = ph->GetName();
1871 if ( pnam.size() == 0 )
continue;
1872 if (
m_LogLevel >= 2 ) cout << myname <<
"Hist:Plot name: " << hnam <<
":" << pnam <<
endl;
1874 Index wpadx = isDist ? 700 : 1400;
1877 Name plotOpt = isDist ?
"hist" :
"p";
1878 pman->
add(ph, plotOpt,
false);
1883 bool doRange =
false;
1884 float ymin = ph->GetMinimum();
1885 float ymax = ph->GetMaximum();
1898 if ( yopt ==
"pamp") {
1904 cout << myname <<
"WARNING: Scaling option pamp requested without run data." <<
endl;
1906 }
else if ( yopt ==
"pampg14") {
1912 cout << myname <<
"WARNING: Scaling option pampg14 requested without run data." <<
endl;
1914 }
else if ( yopt ==
"nevt") {
1917 if ( yfac != 0.0 ) {
1922 if ( ymin > ymax && ymin > 0.0 ) {
1923 int nval = ph->GetNbinsX();
1925 for (
int ival=0; ival<nval; ++ival ) tmpvals[ival] = ph->GetBinContent(ival+1);
1926 std::sort(tmpvals.begin(), tmpvals.end());
1927 float ymed = 0.5*(tmpvals[(nval-1)/2] + tmpvals[nval/2]);
1929 ymin = ymed - 0.5*width;
1930 ymax = ymin + width;
1932 if ( ymax > ymin ) {
1933 if (
m_LogLevel >= 2 ) cout << myname <<
"Setting plot range to (" << ymin <<
", " << ymax <<
")" <<
endl;
1935 TH1* php = pman->
hist();
1936 double del = 1.e-4*(ymax -ymin);
1938 for (
int ibin=1; ibin<php->GetNbinsX(); ++ibin ) {
1939 if ( php->GetBinContent(ibin) > ymax ) php->SetBinContent(ibin, ymax-del);
1940 if ( php->GetBinContent(ibin) < ymin ) php->SetBinContent(ibin, ymin+del);
1945 bool highlightBadChannels = ! isDist;
1946 if ( highlightBadChannels ) {
1947 TH1* php = pman->
hist();
1949 TGraph* pgb =
new TGraph;
1950 TGraph* pgn =
new TGraph;
1951 pgb->SetMarkerStyle(4);
1952 pgb->SetMarkerColor(cols.
red());
1953 pgn->SetMarkerStyle(4);
1954 pgn->SetMarkerColor(cols.
brown());
1955 Index icha0 = php->GetBinLowEdge(1);
1958 for (
int ibin=1; ibin<php->GetNbinsX(); ++ibin ) {
1962 pgb->SetPoint(nbad++, icha+0.5, php->GetBinContent(ibin));
1965 pgn->SetPoint(nnoi++, icha+0.5, php->GetBinContent(ibin));
1968 if ( nnoi ) pman->
add(pgn,
"P");
1969 if ( nbad ) pman->
add(pgb,
"P");
1982 if (
m_LogLevel >= 1 ) cout << myname <<
"Plotting channel summary " << pnam <<
endl;
1993 sman.
replace(isub.first, isub.second);
code to link reconstructed objects back to the MC truth information
const TimeOffsetTool * m_pTickOffsetTool
std::vector< float > FloatVector
bool havePulserPeriod() const
void writeChanSumPlots() const
const AdcChannelStringTool * m_adcStringBuilder
HistInfoMap sumHistTemplates
Index pulserAmplitude() const
IndexByIndexMap channelStatuses
Index m_ChannelLineModulus
void writeSumPlots(const DataMap *pdmin) const
void writeSumHists() const
bool havePulserSource() const
const RunDataTool * m_pRunDataTool
void writeRoiPlots(const HistVector &hists, const AdcChannelData &acd) const
float getSumPlotWidth(Name hnam) const
const AdcIndex AdcChannelStatusNoisy
int add(unsigned int ipad, TObject *pobj, std::string sopt="", bool replace=false)
DataMap & setStatus(int stat)
IndexVector m_ChannelLinePattern
IndexByNameMap sumHistChannels
IndexByNameMap chanSumChaBegin
ChannelGroupService::Name Name
int replace(std::string substr, const T &xsub)
std::pair< AdcIndex, AdcIndex > AdcRoi
int setCanvasSize(int wx, int wy)
const IntVector & getIntVector(Name name) const
const AdcFlag AdcUnderflow
int split(Index nx, Index ny)
void fillChanSumHists() const
std::vector< Index > IndexVector
FloatMap chanSumPlotYMins
const FloatVector & getFloatVector(Name name) const
TH1 * getSumHist(Name hnam)
void writeRoiHists(const DataMap &res, int dbg) const
QTextStream & hex(QTextStream &s)
std::vector< DataMap > DataMapVector
std::vector< TH1 * > HistVector
int shiftHistFit(TH1 *ph, TF1 *pf, std::string fopt, int ipar, double xshift)
DataMap close(const DataMap *dmin) override
const std::string & str() const
NameVector m_ChannelRanges
int showOverflow(bool show=true)
NameMap chanSumHistErrorTypes
DataMap viewMap(const AdcChannelDataMap &acds) const override
std::vector< int > IntVector
std::vector< Name > NameVector
void setIntVector(Name name, const IntVector &val)
int addHorizontalLine(double yoff=0.0, double lenfrac=1.0, int isty=1)
void setChannelInfo(ChannelInfoPtr pchi)
int quietHistFit(TH1 *ph, std::string fname, std::string fopt)
void setHistVector(Name name, const HistVector &hsts, bool own=false)
const AdcFlag AdcOverflow
Name getSumFitName(Name hnam) const
Name m_ChanSumRootFileName
Index pulserPeriod() const
NameMap chanSumHistTemplateNames
Name getChanSumHistVariableType(Name hnam) const
FloatMap chanSumPlotYMaxs
AdcRoiViewer(fhicl::ParameterSet const &ps)
Index getChannelStatus(Index icha) const
T get(std::string const &key) const
int showUnderflow(bool show=true)
void setEventInfo(EventInfoPtr pevi)
int addAxis(bool flag=true)
Name getSumPlotName(Name hnam) const
void setInt(Name name, int val)
int doView(const AdcChannelData &acd, int dbg, DataMap &dm) const
IndexByNameMap chanSumHistTypes
HistVectorMap sumPlotHists
static constexpr double ps
Name label(Index ilab=0) const
TPadManipulator * man(unsigned int ipad=0)
Name getChanSumHistErrorType(Name hnam) const
IndexByNameMap chanSumChaEnd
DataMap view(const AdcChannelData &acd) const override
int addVerticalModLines(double xmod, double xoff=0.0, double lenfrac=1.0, int isty=3)
Name getChanSumHistTemplateName(Name hnam) const
Float getFloat(Name name, Float def=0.0) const
std::vector< int > IntVector
void setPlotLabels(Name &sttl) const
Index channelStatus() const
int fit(TH1 *ph, double mean0) const
int addHistFun(unsigned int ifun=0)
Name getChanSumPlotName(Name hnam) const
int getInt(Name name, int def=0) const
std::unique_ptr< TPadManipulator > TpmPtr
bool haveFloat(Name name) const
TF1 * coldelecResponseTF1(double gainIn, double shapingIn, double t0, std::string fname="ceresp")
NameMap chanSumHistVariableTypes
int setRangeX(double x1, double x2)
int addVerticalLine(double xoff=0.0, double lenfrac=1.0, int isty=1)
void writeChanSumHists() const
std::map< AdcChannel, AdcChannelData > AdcChannelDataMap
const AdcIndex AdcChannelStatusBad
Dft::FloatVector FloatVector
auto const & get(AssnsNode< L, R, D > const &r)
void fillSumHists(const AdcChannelData &acd, const DataMap &dm) const
void setFloatVector(Name name, const FloatVector &val)
std::vector< TH1 * > HistVector
int setRangeY(double y1, double y2)
double mean(sqlite3 *db, std::string const &table_name, std::string const &column_name)
IndexByIndexMap eventCallCount
std::string to_string(ModuleType const mt)
const IndexRangeTool * m_pChannelRangeTool
int print(std::string fname, std::string spat="{,}")
AdcLongIndex triggerClock() const
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
QTextStream & endl(QTextStream &s)
bool havePulserAmplitude() const
void setLogLevel(Index lev)