22 #include "TGraphErrors.h" 26 #include "TDirectory.h" 35 using std::istringstream;
49 bool runHasChanged =
false;
50 if ( callCount == 0 ) {
57 if ( run != lastRun ) {
61 if ( event != lastEvent ) ++eventCount;
74 : m_LogLevel(ps.
get<
int>(
"LogLevel")),
75 m_Metric(ps.
get<
Name>(
"Metric")),
76 m_DataView(ps.
get<
Name>(
"DataView")),
77 m_PedestalReference(ps.
get<
Name>(
"PedestalReference")),
78 m_MetricSummaryView(ps.
get<
Name>(
"MetricSummaryView")),
82 m_MetricBins(ps.
get<
Index>(
"MetricBins")),
83 m_ChannelLineModulus(ps.
get<
Index>(
"ChannelLineModulus")),
85 m_ChannelLinePatternSolid(ps.
get<
IndexVector>(
"ChannelLinePatternSolid")),
86 m_HistName(ps.
get<
Name>(
"HistName")),
87 m_HistTitle(ps.
get<
Name>(
"HistTitle")),
88 m_MetricLabel(ps.
get<
Name>(
"MetricLabel")),
89 m_PlotSizeX(ps.
get<
Index>(
"PlotSizeX")),
90 m_PlotSizeY(ps.
get<
Index>(
"PlotSizeY")),
91 m_PlotFileName(ps.
get<
Name>(
"PlotFileName")),
92 m_PlotUsesStatus(ps.
get<
int>(
"PlotUsesStatus")),
93 m_RootFileName(ps.
get<
Name>(
"RootFileName")),
95 m_mdRead(false), m_mdWrite(false), m_mdWarnAbsent(false), m_mdWarnPresent(false),
98 m_doSummaryError(false),
99 m_pPedestalReference(nullptr),
100 m_pChannelStatusProvider(nullptr),
102 const string myname =
"AdcChannelMetric::ctor: ";
103 string stringBuilder =
"adcStringBuilder";
107 if ( mflag ==
"read" )
m_mdRead =
true;
108 else if ( mflag ==
"write" )
m_mdWrite =
true;
112 cout << myname <<
"WARNING: Ignoring invalid metadata flag: " << mflag <<
endl;
116 bool toolNotFound =
false;
119 if ( crn.size() == 0 ) {
120 m_crs.emplace_back(
"all", 0, 0,
"All");
122 if ( pcrt ==
nullptr && !toolNotFound ) {
124 if ( pcrt ==
nullptr ) {
125 cout << myname <<
"ERROR: IndexRangeTool not found: channelRanges" <<
endl;
128 if ( pcrt !=
nullptr ) {
131 m_crs.push_back(ran);
133 cout << myname <<
"WARNING: Channel range not found: " << crn <<
endl;
148 cout << myname <<
"Pedestal reference array has " << nref <<
" value" 149 << ( nref == 1 ?
"" :
"s" );
150 if ( nref ) cout <<
" starting at channel " << off;
157 cout << myname <<
"WARNING: AdcChannelStringTool not found: " << stringBuilder <<
endl;
161 string stnam =
"runDataTool";
164 cout << myname <<
"ERROR: RunDataTool " << stnam
165 <<
" not found. Metric limits will not be evaluated." <<
endl;
167 cout << myname <<
"RunDataTool retrieved." <<
endl;
173 const std::set<Name> sumVals = {
"count",
"mean",
"rms",
"drms"};
181 Name::size_type ipos = vnam.find(
":");
182 if ( ipos != Name::npos ) {
183 enam = vnam.substr(ipos+1);
184 vnam = vnam.substr(0, ipos);
187 cout << myname <<
"WARNING: Invalid value for metric summary view reset from " << vnam
188 <<
" to mean." <<
endl;
193 cout << myname <<
"WARNING: Ignoring invalid error for metric summary view: " << enam <<
endl;
203 if (
m_LogLevel >= 1 ) cout << myname <<
"Fetching channel status service." <<
endl;
206 cout << myname <<
"WARNING: Channel status provider not found." <<
endl;
212 cout << myname <<
"Configuration: " <<
endl;
224 cout << myname <<
" ChannelRanges: [";
227 if ( ! first ) cout <<
", ";
236 cout << myname <<
" ChannelLinePattern: {";
239 if ( ! first ) cout <<
", ";
244 cout << myname <<
" ChannelLinePatternSolid: {";
247 if ( ! first ) cout <<
", ";
252 cout << myname <<
" ChannelCounts: {";
255 if ( ! first ) cout <<
", ";
268 cout << myname <<
" MetadataFlags: [";
270 for (
string mflag : m_MetadataFlags ) {
271 if ( ! first ) cout <<
", ";
284 const string myname =
"AdcChannelMetric::dtor: ";
287 Index nchaDataMax = 0;
289 Index weightSumMax = 0.0;
290 for (
const MetricSummaryMap::value_type& imsm :
getState().crsums ) {
294 cout << myname <<
"Channel range " << cr.
name <<
endl;
296 for (
Index kcha=0; kcha<cr.
size(); ++kcha ) {
315 for (
Index kcha=0; kcha<cr.
size(); ++kcha ) {
322 if (
m_LogLevel >=3 ) cout << myname <<
"Channel: summary value: " << icha <<
": " << met.
value;
347 if ( ncha ) w = log10(valmax) + 1.01;
348 cout << myname <<
"Summary for metric " <<
m_Metric <<
endl;
353 cout << myname <<
" Maximum # entries for a channel: " <<
setw(w) << countMax <<
endl;
354 cout << myname <<
" Maximum weight sum for a channel: " <<
setw(w) << weightSumMax <<
endl;
355 cout << myname <<
" Total # channels in ranges: " <<
setw(w) << ncha <<
endl;
356 cout << myname <<
" # channels without data: " <<
setw(w) << ncha - nchaData <<
endl;
357 cout << myname <<
" # channels with data: " <<
setw(w) << nchaData <<
endl;
358 cout << myname <<
" # channels with max # entries: " <<
setw(w) << nchaDataMax <<
endl;
361 for (
const MetricSummaryMap::value_type& imsm :
getState().crsums ) {
363 cout <<
"============= Channel range " << cr.
name <<
endl;
366 if ( msum.eventCount ) {
367 cout <<
"------------- " <<
m_Metric <<
"[" << icnt++ <<
"]" <<
endl;
368 cout << myname <<
" weight flag: " <<
setw(w) << msum.weightFlag <<
endl;
369 cout << myname <<
" # events: " <<
setw(w) << msum.eventCount <<
endl;
370 cout << myname <<
" # weighted events: " <<
setw(w) << msum.weightedEventCount <<
endl;
371 cout << myname <<
" Neff: " <<
setw(w) << msum.neff() <<
endl;
372 cout << myname <<
" mean: " <<
setw(w) << msum.mean() <<
" +/- " 374 cout << myname <<
" RMS: " <<
setw(w) << msum.rms() <<
" +/- " 376 cout << myname <<
" center: " <<
setw(w) << msum.center() <<
" +/- " 377 <<
setw(w) << 0.5*msum.range() <<
endl;
380 cout <<
"===================================" <<
endl;
389 const string myname =
"AdcChannelMetric::initialize: ";
390 if ( !force &&
getState().initCount )
return;
391 if (
m_LogLevel >= 1 ) cout << myname <<
"Initializing " <<
m_crs.size()
392 <<
" channel ranges." <<
endl;
396 for (
Index icha =ran.begin; icha<ran.end; ++icha ) {
401 if (
m_LogLevel >= 1 ) cout << myname <<
"Initialized " << ncha <<
" channels." <<
endl;
408 const string myname =
"AdcChannelMetric::view: ";
414 if ( rstat )
return ret.
setStatus(rstat);
425 const string myname =
"AdcChannelMetric::viewMap: ";
433 const string myname =
"AdcChannelMetric::update: ";
438 cout <<
"WARNING: Run-event-channel " << acd.
run() <<
"-" << acd.
event() <<
"-" 439 << acd.
channel() <<
" already has metadata field " << mnam <<
endl;
441 float mval = ret.
getFloat(
"metricValue");
450 const string myname =
"AdcChannelMetric::updateMap: ";
455 for (
const auto& imet : mets ) {
456 Index icha = imet.first;
458 if ( iacd == acds.end() ) {
459 cout << myname <<
"ERROR: Channel map is missing channel " << icha <<
endl;
463 cout <<
"WARNING: Run-event-channel " << acd.
run() <<
"-" << acd.
event() <<
"-" 464 << acd.
channel() <<
" already has metadata field " << mnam <<
endl;
466 float mval = imet.second.value;
477 const string myname =
"AdcChannelMetric::viewMapLocal: ";
479 if ( acds.size() == 0 ) {
480 cout << myname <<
"Input channel map is empty." <<
endl;
483 Index chanFirst = acds.begin()->first;
484 Index chanLast = acds.rbegin()->first;
485 if (
m_LogLevel >= 2 ) cout << myname <<
"Processing " << acds.size() <<
" channels: [" 486 << chanFirst <<
", " << chanLast <<
"]" <<
endl;
488 if ( ran.name ==
"all" ) {
489 ran.begin = chanFirst;
490 ran.end = chanLast + 1;
503 const string myname =
"AdcChannelMetric::viewMapForOneRange: ";
512 if (
getState().
update(iacd1->second.run(), iacd1->second.event()) ) {
516 if ( metricSums.size() < ran.
size() ) metricSums.resize(ran.
size());
524 cout << myname <<
"WARNING: Metric evaluation failed for metric " <<
m_Metric 528 Index icha = iacd->first;
529 mets[icha].setValue(met);
531 metricSum.
add(met, wt);
533 cout << myname <<
" Chan: met, wt (wsum, range): " << icha <<
": " << met <<
", " << wt
536 ichas.push_back(icha);
565 const string myname =
"AdcChannelMetric::getMetric: ";
571 if ( nent && pacd0 ==
nullptr ) {
572 cout << myname <<
"ERROR: Channel " << acdtop.
channel() <<
" view " <<
m_DataView 573 <<
" is missing its first entry." <<
endl;
576 if ( nent ) weight = 1.0;
577 if ( met ==
"pedestal" ) {
579 sunits =
"ADC count";
580 }
else if ( met ==
"pedestalDiff" ) {
589 if ( ipdr == pedRefs.end() ) {
590 pedRefs[icha].value =
val;
593 val -= ipdr->second.value;
596 cout << myname <<
"WARNING: Pedestal difference requested without reference." <<
endl;
598 sunits =
"ADC count";
599 }
else if ( met ==
"pedestalRms" ) {
601 sunits =
"ADC count";
602 }
else if ( met ==
"time" ) {
605 }
else if ( met ==
"fembID" ) {
607 }
else if ( met ==
"fembChannel" ) {
609 }
else if ( met ==
"apaFembID" ) {
611 }
else if ( met ==
"asic" ) {
613 }
else if ( met ==
"nraw" ) {
617 }
else if ( met ==
"nsam" ) {
621 }
else if ( met ==
"rawRms" ) {
624 for (
Index ient=0; ient<nent; ++ient ) {
628 double dif = double(sig) - ped;
633 val = nsam == 0 ? 0.0 : sqrt(sum/nsam);
635 }
else if ( met ==
"samRms" ) {
638 for (
Index ient=0; ient<nent; ++ient ) {
640 for (
double sig : pacd->
samples ) {
645 val = nsam == 0 ? 0.0 : sqrt(sum/nsam);
647 }
else if ( met.substr(0, 6) ==
"samRms" ) {
650 istringstream sscnt(met.substr(6));
653 std::vector<float> samSums;
655 cout << myname <<
"WARNING: Invalid metric: " << met <<
endl;
658 for (
Index ient=0; ient<nent; ++ient ) {
662 for (
Index isam=0; isam<nsam; ++isam ) {
666 if ( samCount == ncnt ) {
667 samSums.push_back(samSum);
674 if ( samSums.size() ) {
676 for (
float samSum : samSums ) sum += samSum*samSum;
677 val = sqrt(sum/samSums.size());
678 weight = samSums.size();
680 }
else if ( met ==
"sigRms" || met ==
"nsgRms" ) {
684 bool doSignal = met ==
"sigRms";
685 for (
Index ient=0; ient<nent; ++ient ) {
688 if ( pacd->
signal.size() != nsam ) {
689 cout << myname <<
"WARNING: signal and sample sizes differ";
691 cout <<
": " << pacd->
signal.size() <<
" != " << nsam <<
"." <<
endl;
693 for (
Index isam=0; isam<nsam; ++isam ) {
694 if ( pacd->
signal[isam] == doSignal ) {
695 double sig = pacd->
samples[isam];
703 val = nsum == 0 ? 0.0 : sqrt(sum/nsum);
706 cout << myname <<
"Sample count for " << met <<
" for channel " << acdtop.
channel();
708 cout <<
": " << nsum <<
"/" << nsamtot <<
"." 709 <<
" " << met <<
" = " << val <<
endl;
712 }
else if ( met.substr(0, 6) ==
"nsgRms" ) {
715 istringstream sscnt(met.substr(6));
718 std::vector<float> samSums;
720 cout << myname <<
"WARNING: Invalid metric: " << met <<
endl;
722 for (
Index ient=0; ient<nent; ++ient ) {
725 if ( pacd->
signal.size() != nsam ) {
726 cout << myname <<
"WARNING: signal and sample sizes differ";
728 cout <<
" metric " << met <<
": " << pacd->
signal.size() <<
" != " << nsam <<
"." <<
endl;
731 for (
Index isam0=0; isam0+ncnt<=nsam; ++isam0 ) {
732 bool foundSignal =
false;
734 for (
Index icnt=0; icnt<ncnt; ++icnt ) {
735 Index isam = isam0 + icnt;
736 if ( pacd->
signal[isam] ) {
743 if ( foundSignal )
break;
744 samSums.push_back(samSum);
748 if ( samSums.size() ) {
750 for (
float samSum : samSums ) sum += samSum*samSum;
751 val = sqrt(sum/samSums.size());
752 weight = samSums.size();
754 }
else if ( met ==
"sigFrac" ) {
757 for (
Index ient=0; ient<nent; ++ient ) {
760 if ( pacd->
signal.size() != nsam ) {
761 cout << myname <<
"WARNING: Signal and sample sizes differ for sigFrac";
763 cout <<
": " << pacd->
signal.size() <<
" != " << nsam <<
"." <<
endl;
765 for (
Index isam=0; isam<nsam; ++isam ) {
767 if ( pacd->
signal[isam] ) ++nsig;
771 val = nsamtot > 0 ?
float(nsig)/
float(nsamtot) : 0.0;
772 }
else if ( met ==
"rawTailFraction" ) {
775 for (
Index ient=0; ient<nent; ++ient ) {
780 double dif = double(sig) - ped;
781 if ( fabs(dif) > lim ) ++ntail;
785 val = nsam > 0 ? double(ntail)/nsam : 0.0;
786 }
else if ( nent == 1 && pacd0->
hasMetadata(met) ) {
788 cout << myname <<
"WARNING: Channel " << acdtop.
channel()
789 <<
" filling metadata only for the first of " << nent
790 <<
" entries." <<
endl;
792 val = pacd0->
metadata.find(met)->second;
795 }
else if ( met.find(
"+") != string::npos ) {
797 string metsrem = met;
798 string::size_type ipos = 0;
800 while ( ipos != string::npos ) {
801 ipos = metsrem.find(
"+");
802 string newmet = metsrem.substr(0, ipos);
805 int sstat =
getMetric(acdtop, newmet, newval, sunits, newwt);
807 cout << myname <<
"ERROR: Invalid sub-metric name: " << newmet <<
endl;
810 if ( newwt != 1.0 ) {
811 cout << myname <<
"Evaluation of sub-metric " << newmet <<
" for metric " << met
812 <<
" returned non-unity weight " << newwt <<
endl;
816 if ( ipos == string::npos )
break;
817 metsrem = metsrem.substr(ipos + 1);
820 cout << myname <<
"ERROR: Invalid metric name: " << met <<
endl;
824 cout << myname <<
setw(20) << met <<
": " << val <<
endl;
839 if ( pnbl ==
nullptr )
return name;
843 return pnbl->
build(acd, dm, name);
850 Name ofpname,
Name ofrname,
bool useErrors)
const {
851 const string myname =
"AdcChannelMetric::processMetricsForOneRange: ";
853 NameVector statNames = {
"All",
"Good",
"Bad",
"Noisy"};
856 Name hname = ph->GetName();
857 Name htitl = ph->GetTitle();
860 if (
m_LogLevel >= 2 ) cout << myname <<
"Plotting # channels vs. metric. Count is " << mets.size() <<
endl;
861 for ( MetricMap::value_type imet : mets ) {
862 double met = imet.second.value;
865 if ( ofpname.size() ) {
876 Name slaby = ph->GetYaxis()->GetTitle();
879 if (
m_LogLevel >= 2 ) cout << myname <<
"Plotting metric vs. channel. Count is " << mets.size() <<
endl;
880 for (
Index igra=0; igra<ngraph; ++igra ) {
881 string gname = hname;
882 string gtitl = htitl;
884 smanName.
replace(
"%STATUS%", statNames[igra]);
886 smanTitl.
replace(
"%STATUS%", statNames[igra]);
888 egraphs[igra] =
new TGraphErrors;
889 graphs[igra] = egraphs[igra];
891 graphs[igra] =
new TGraph;
893 TGraph* pg = graphs[igra];
894 pg->SetName(gname.c_str());
895 pg->SetTitle(gtitl.c_str());
896 if ( ! useErrors ) pg->SetMarkerStyle(2);
897 pg->SetMarkerColor(statCols[igra]);
898 pg->SetLineColor(statCols[igra]);
899 pg->GetXaxis()->SetTitle(
"Channel");
900 pg->GetYaxis()->SetTitle(slaby.c_str());
902 TGraph* pgAll = graphs[0];
903 TGraphErrors* pgeAll = egraphs[0];
907 for ( MetricMap::value_type imet : mets ) {
908 Index icha = imet.first;
909 double met = imet.second.value;
910 double err = imet.second.error;
912 cout << myname <<
" " << met <<
": " << met <<
" +/- " << err <<
endl;
915 ph->SetBinContent(bin, met);
916 if ( err ) ph->SetBinError(bin, err);
918 Index iptAll = pgAll->GetN();
919 float xcha = icha + 0.5;
920 pgAll->SetPoint(iptAll, xcha, gval);
921 if ( pgeAll !=
nullptr ) pgeAll->SetPointError(iptAll, ex, err);
925 TGraph* pgStat = graphs[
stat];
926 TGraphErrors* pgeStat = egraphs[
stat];
927 Index iptStat = pgStat->GetN();
928 pgStat->SetPoint(iptStat, xcha, gval);
929 if ( pgeStat !=
nullptr ) pgeStat->SetPointError(iptStat, ex, err);
934 if (
m_LogLevel >= 3 ) cout << myname <<
"Filled " << nfill <<
" channels." <<
endl;
935 if ( ofpname.size() && nfill > 0 ) {
942 for (
int igra : {1, 3, 2} ) {
943 TGraph* pgra = graphs[igra];
944 if ( pgra->GetN() ) man.
add(pgra,
"P");
957 if ( icha > icha0 && icha < ran.
last() ) {
962 if ( icha > icha0 && icha < ran.
last() ) {
970 if ( mmax > mmin ) man.
setRangeY(mmin, mmax);
976 cout << myname <<
"Created plot ";
977 cout <<
"for " << nfill <<
" channels in range " << ran.
name <<
endl;
978 cout << myname <<
" Output file: " << ofpname <<
endl;
981 if ( ofrname.size() ) {
982 TFile* pfile = TFile::Open(ofrname.c_str(),
"UPDATE");
984 if (
m_LogLevel > 1 ) cout << myname <<
"Wrote " << ph->GetName() <<
" to " << ofrname <<
endl;
998 ph =
new TH1F(hname.c_str(), htitl.c_str(), ran.
size(), ran.
begin, ran.
end);
999 ph->GetXaxis()->SetTitle(
"Channel");
1000 ph->GetYaxis()->SetTitle(slabm.c_str());
1003 ph->GetXaxis()->SetTitle(slabm.c_str());
1004 ph->GetYaxis()->SetTitle(
"# channels");
1006 ph->SetDirectory(
nullptr);
1007 ph->SetLineWidth(2);
1016 if ( icha >= stats.size() ) stats.resize(icha + 1, 0);
1029 const string myname =
"AdcChannelMetric::evaluateFormulas: ";
1034 cout << myname <<
"WARNING: RunData not found for run " << run <<
"." <<
endl;
1045 cout << myname <<
"WARNING: Using default metric min " << mmin <<
endl;
1051 cout << myname <<
"WARNING: Using default metric max " << mmax <<
endl;
virtual bool IsBad(raw::ChannelID_t channel) const =0
Returns whether the specified channel is bad in the current run.
void setValue(double a_value)
int setGridY(bool flag=true)
const FloatArrayTool * m_pPedestalReference
DataMap update(AdcChannelData &acd) const override
DataMap viewMapLocal(const AdcChannelDataMap &acds, MetricMap &mets) const
void setFloat(Name name, float val)
int add(unsigned int ipad, TObject *pobj, std::string sopt="", bool replace=false)
DataMap & setStatus(int stat)
void evaluateFormulas() const
const AdcChannelStringTool * m_adcStringBuilder
virtual bool IsNoisy(raw::ChannelID_t channel) const =0
Returns whether the specified channel is noisy in the current run.
Name nameReplace(Name name, const AdcChannelData &acd, const IndexRange &ran) const
Index m_ChannelLineModulus
int replace(std::string substr, const T &xsub)
int setCanvasSize(int wx, int wy)
NameVector m_ChannelRanges
const lariov::ChannelStatusProvider * m_pChannelStatusProvider
std::vector< MetricSummary > MetricSummaryVector
void setHist(Name name, TH1 *ph, bool own=false)
std::vector< Name > NameVector
DataMap view(const AdcChannelData &acd) const override
void processMetricsForOneRange(const IndexRange &ran, const MetricMap &mets, TH1 *ph, Name ofname, Name ofrname, bool useErrors) const
void setError(double a_error)
int showOverflow(bool show=true)
static constexpr double ms
void setIntVector(Name name, const IntVector &val)
IndexVector m_ChannelCounts
void setString(Name name, String val)
bool hasMetadata(Name mname) const
std::vector< Index > IndexVector
Index fembChannel() const
bool update(Index run, Index event)
int showUnderflow(bool show=true)
Index channelStatus(Index icha) const
void setEventInfo(EventInfoPtr pevi)
int addAxis(bool flag=true)
~AdcChannelMetric() override
NameVector m_MetadataFlags
void setInt(Name name, int val)
void initialize(bool force=false)
DataMap updateMap(AdcChannelDataMap &acds) const override
AdcChannelMetric(fhicl::ParameterSet const &ps)
static int max(int a, int b)
static constexpr double ps
Name label(Index ilab=0) const
virtual int getMetric(const AdcChannelData &acd, Name met, double &metricValue, Name &metricUnits, double &metricWeight) const
IndexVector m_ChannelLinePattern
void err(const char *fmt,...)
int addVerticalModLines(double xmod, double xoff=0.0, double lenfrac=1.0, int isty=3)
Q_EXPORT QTSManip setw(int w)
Float getFloat(Name name, Float def=0.0) const
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
int setRangeX(double x1, double x2)
const AdcChannelData * viewEntry(Name vpnam, AdcIndex ient) const
double getValue(Name vnam) const
int addVerticalLine(double xoff=0.0, double lenfrac=1.0, int isty=1)
QTextStream & bin(QTextStream &s)
DataMap viewMapForOneRange(const AdcChannelDataMap &acds, const IndexRange &ran, MetricMap &mets) const
Interface for experiment-specific channel quality info provider.
void setMetadata(Name mname, float val)
std::map< AdcChannel, AdcChannelData > AdcChannelDataMap
static bool isValueName(Name vnam)
auto const & get(AssnsNode< L, R, D > const &r)
Interface for experiment-specific service for channel quality info.
void setFloatVector(Name name, const FloatVector &val)
DataMap viewMap(const AdcChannelDataMap &acds) const override
IndexVector channelStatuses
SetStat setFormulaPars(TFormula *form)
int setRangeY(double y1, double y2)
TH1 * createHisto(const AdcChannelData &acd, const IndexRange &ran) const
int print(std::string fname, std::string spat="{,}")
IndexVector m_ChannelLinePatternSolid
QTextStream & endl(QTextStream &s)
Event finding and building.
std::map< Index, Metric > MetricMap
void add(double val, double weight)