7 #include <TStopwatch.h>
9 #include "PixTestPretest.hh"
21 fTargetIa(-1), fNoiseWidth(22), fNoiseMargin(10),
24 fParDeltaVthrComp(-50),
31 PixTestPretest::PixTestPretest() :
PixTest() {
42 std::transform(parName.begin(), parName.end(), parName.begin(), ::tolower);
43 for (
unsigned int i = 0; i <
fParameters.size(); ++i) {
46 sval.erase(
remove(sval.begin(), sval.end(),
' '), sval.end());
48 if (!parName.compare(
"targetia")) {
49 fTargetIa = atoi(sval.c_str());
52 if (!parName.compare(
"noisewidth")) {
53 fNoiseWidth = atoi(sval.c_str());
56 if (!parName.compare(
"noisemargin")) {
57 fNoiseMargin = atoi(sval.c_str());
60 if (!parName.compare(
"ntrig") ) {
61 fParNtrig = atoi(sval.c_str() );
64 if (!parName.compare(
"vcal") ) {
65 fParVcal = atoi(sval.c_str() );
68 if (!parName.compare(
"deltavthrcomp") ) {
69 fParDeltaVthrComp = atoi(sval.c_str() );
72 if (!parName.compare(
"fraccaldel") ) {
73 fParFracCalDel = atof(sval.c_str() );
76 if (!parName.compare(
"pix") || !parName.compare(
"pix1") ) {
78 if (string::npos != s1) {
79 str1 = sval.substr(0, s1);
80 pixc = atoi(str1.c_str());
81 str2 = sval.substr(s1+1);
82 pixr = atoi(str2.c_str());
84 fPIX.push_back( make_pair(pixc, pixr) );
89 LOG(logDEBUG) <<
" clear fPIX: " <<
fPIX.size();
100 void PixTestPretest::init() {
102 fDirectory = gFile->GetDirectory(fName.c_str());
112 fTestTip = string(
"Pretest: set Vana, VthrComp, and CalDel")
113 + string(
"\ntune PH into ADC range using VOffsetRO and VIref_ADC")
115 fSummaryTip = string(
"summary plot to be implemented");
119 void PixTestPretest::bookHist(
string name) {
122 LOG(logDEBUG) <<
"nothing done with " << name;
126 PixTestPretest::~PixTestPretest() {
127 LOG(logDEBUG) <<
"PixTestPretest dtor";
137 bigBanner(Form(
"PixTestPretest::doTest()"));
140 TH1 *h1 = (*fDisplayedHist);
145 bigBanner(
"ERROR: some ROCs are not programmable; stop");
150 h1 = (*fDisplayedHist);
155 h1 = (*fDisplayedHist);
160 h1 = (*fDisplayedHist);
167 int seconds = t.RealTime();
168 LOG(logINFO) <<
"PixTestPretest::doTest() done, duration: " << seconds <<
" seconds";
173 std::transform(command.begin(), command.end(), command.begin(), ::tolower);
174 LOG(logDEBUG) <<
"running command: " << command;
175 if (!command.compare(
"programroc")) {
179 if (!command.compare(
"setcaldel")) {
183 if (!command.compare(
"savedacs")) {
187 if (!command.compare(
"setvana")) {
191 if (!command.compare(
"findworkingpixel")) {
195 if (!command.compare(
"setvthrcompcaldel")) {
199 if (!command.compare(
"setvthrcompid")) {
204 LOG(logDEBUG) <<
"did not find command ->" << command <<
"<-";
209 void PixTestPretest::setVana() {
213 banner(Form(
"PixTestPretest::setVana() target Ia = %d mA/ROC", fTargetIa));
217 vector<uint8_t> vanaStart;
218 vector<double> rocIana;
222 for (
int iroc = 0; iroc < nRocs; ++iroc) {
224 rocIana.push_back(0.);
236 }
while (sw.RealTime() < 0.1);
239 double i015 = (nRocs-1) * i016 / nRocs;
240 LOG(logDEBUG) <<
"offset current from other " << nRocs-1 <<
" ROCs is " << i015 <<
" mA";
244 const double extra = 0.1;
245 const double eps = 0.25;
246 const double slope = 6;
248 for (
int roc = 0; roc < nRocs; ++roc) {
250 LOG(logDEBUG) <<
"skipping ROC idx = " << roc <<
" (not selected) for Vana tuning";
253 int vana = vanaStart[roc];
261 }
while (sw.RealTime() < 0.1);
263 double diff = fTargetIa + extra - (ia - i015);
266 LOG(logDEBUG) <<
"ROC " << roc <<
" iter " << iter
268 <<
" Ia " << ia-i015 <<
" mA";
270 while (TMath::Abs(diff) > eps && iter < 11 && vana > 0 && vana < 255) {
272 int stp =
static_cast<int>(TMath::Abs(slope*diff));
273 if (stp == 0) stp = 1;
274 if (diff < 0) stp = -stp;
294 while( sw.RealTime() < 0.1 );
296 diff = fTargetIa + extra - (ia - i015);
298 LOG(logDEBUG) <<
"ROC " << setw(2) << roc
299 <<
" iter " << setw(2) << iter
300 <<
" Vana " << setw(3) << vana
301 <<
" Ia " << ia-i015 <<
" mA";
304 rocIana[roc] = ia-i015;
305 vanaStart[roc] = vana;
310 TH1D *hsum =
bookTH1D(
"VanaSettings",
"Vana per ROC", nRocs, 0., nRocs);
314 hsum->SetMaximum(256);
317 TH1D *hcurr =
bookTH1D(
"Iana",
"Iana per ROC", nRocs, 0., nRocs);
320 hcurr->SetMinimum(0);
321 hcurr->SetMaximum(30.0);
326 for (
int roc = 0; roc < nRocs; ++roc) {
329 LOG(logDEBUG) <<
"ROC " << setw(2) << roc <<
" Vana " << setw(3) << int(vanaStart[roc]);
332 hsum->Fill(roc, vanaStart[roc] );
333 hcurr->Fill(roc, rocIana[roc]);
343 while( sw.RealTime() < 0.1 );
350 LOG(logINFO) <<
"PixTestPretest::setVana() done, Module Ia " << ia16 <<
" mA = " << ia16/nRocs <<
" mA/ROC";
356 void PixTestPretest::setVthrCompCalDel() {
357 uint16_t FLAGS = FLAG_FORCE_MASKED;
362 banner(Form(
"PixTestPretest::setVthrCompCalDel()"));
364 string name(
"pretestVthrCompCalDel");
375 h1 =
bookTH1D(Form(
"pretestCalDel"), Form(
"pretestCalDel"), rocIds.size(), 0., rocIds.size());
382 vector<int> calDel(rocIds.size(), -1);
383 vector<int> vthrComp(rocIds.size(), -1);
384 vector<int> calDelE(rocIds.size(), -1);
391 map<int, TH2D*> maps;
392 for (
unsigned int iroc = 0; iroc < rocIds.size(); ++iroc) {
393 h2 =
bookTH2D(Form(
"%s_c%d_r%d_C%d", name.c_str(),
fPIX[ip].first,
fPIX[ip].second, rocIds[iroc]),
394 Form(
"%s_c%d_r%d_C%d", name.c_str(),
fPIX[ip].first,
fPIX[ip].second, rocIds[iroc]),
395 255, 0., 255., 255, 0., 255.);
397 maps.insert(make_pair(rocIds[iroc], h2));
399 h2->SetMaximum(fParNtrig);
405 vector<pair<uint8_t, pair<uint8_t, vector<pixel> > > > rresults;
413 LOG(logCRITICAL) <<
"problem with readout: "<< e.what() <<
" missing " << e.numberMissing <<
" events";
415 if (e.numberMissing > 10) done =
true;
417 LOG(logCRITICAL) <<
"pXar execption: "<< e.what();
420 done = (cnt>5) || done;
426 for (
unsigned i = 0; i < rresults.size(); ++i) {
427 pair<uint8_t, pair<uint8_t, vector<pixel> > > v = rresults[i];
429 pair<uint8_t, vector<pixel> > w = v.second;
431 vector<pixel> wpix = w.second;
432 for (
unsigned ipix = 0; ipix < wpix.size(); ++ipix) {
433 maps[wpix[ipix].roc()]->Fill(idac1, idac2, wpix[ipix].value());
436 for (
unsigned int iroc = 0; iroc < rocIds.size(); ++iroc) {
437 h2 = maps[rocIds[iroc]];
438 TH1D *hy = h2->ProjectionY(
"_py", 5, h2->GetNbinsX());
439 double vcthrMax = hy->GetMaximum();
440 double bottom = hy->FindFirstBinAbove(0.5*vcthrMax);
441 double top = hy->FindLastBinAbove(0.5*vcthrMax);
444 if (fParDeltaVthrComp>0) {
445 vthrComp[iroc] = bottom + fParDeltaVthrComp;
447 vthrComp[iroc] = top + fParDeltaVthrComp;
450 TH1D *h0 = h2->ProjectionX(
"_px", vthrComp[iroc], vthrComp[iroc]);
451 double cdMax = h0->GetMaximum();
452 double cdFirst = h0->GetBinLowEdge(h0->FindFirstBinAbove(0.5*cdMax));
453 double cdLast = h0->GetBinLowEdge(h0->FindLastBinAbove(0.5*cdMax));
454 calDelE[iroc] =
static_cast<int>(cdLast - cdFirst);
455 calDel[iroc] =
static_cast<int>(cdFirst + fParFracCalDel*calDelE[iroc]);
456 TMarker *pm =
new TMarker(calDel[iroc], vthrComp[iroc], 21);
457 pm->SetMarkerColor(kWhite);
458 pm->SetMarkerSize(2);
459 h2->GetListOfFunctions()->Add(pm);
460 pm =
new TMarker(calDel[iroc], vthrComp[iroc], 7);
461 pm->SetMarkerColor(kBlack);
462 pm->SetMarkerSize(0.2);
463 h2->GetListOfFunctions()->Add(pm);
466 h1->SetBinContent(rocIds[iroc]+1, calDel[iroc]);
467 h1->SetBinError(rocIds[iroc]+1, 0.5*calDelE[iroc]);
468 LOG(logDEBUG) <<
"CalDel: " << calDel[iroc] <<
" +/- " << 0.5*calDelE[iroc];
483 string caldelString(
""), vthrcompString(
"");
484 for (
unsigned int iroc = 0; iroc < rocIds.size(); ++iroc){
485 if (calDel[iroc] > 0) {
486 fApi->
setDAC(
"CalDel", calDel[iroc], rocIds[iroc]);
487 caldelString += Form(
" %4d", calDel[iroc]);
489 caldelString += Form(
" _%4d",
fApi->
_dut->
getDAC(rocIds[iroc],
"caldel"));
491 fApi->
setDAC(
"VthrComp", vthrComp[iroc], rocIds[iroc]);
492 vthrcompString += Form(
" %4d", vthrComp[iroc]);
496 LOG(logINFO) <<
"PixTestPretest::setVthrCompCalDel() done";
497 LOG(logINFO) <<
"CalDel: " << caldelString;
498 LOG(logINFO) <<
"VthrComp: " << vthrcompString;
504 void PixTestPretest::setVthrCompId() {
509 banner(Form(
"PixTestPretest::setVthrCompId()"));
516 for (
int roc = 0; roc < nRocs; ++roc) {
518 h1 =
bookTH1D(Form(
"Id_vs_VthrComp_C%d",
int(roc)),
519 Form(
"Id vs VthrComp C%d",
int(roc)),
523 setTitles( h1,
"VthrComp [DAC]",
"ROC digital current [mA]" );
530 for (
int roc = 0; roc < nRocs; ++roc) {
542 while( sw.RealTime() < 0.1 );
544 double i015 = (nRocs-1) * i016 / nRocs;
546 LOG(logINFO) <<
"offset current from other " << nRocs-1 <<
" ROCs is "
553 vector<int> rocVthrComp(nRocs, -1);
554 for (
int roc = 0; roc < nRocs; ++roc) {
557 LOG(logDEBUG) <<
"ROC " << setw(2) << roc;
561 for (
size_t idac = 0; idac < 256; ++idac) {
569 if (hid) hid->Draw();
574 LOG(logDEBUG) <<
"current peak " << hid->GetMaximum()
575 <<
" mA at DAC " << hid->GetMaximumBin();
579 for (
int i = 1; i <= 256-fNoiseWidth; ++i) {
580 double ni = hid->GetBinContent(i);
581 double d = hid->GetBinContent(i+fNoiseWidth) - ni;
587 LOG(logDEBUG) <<
"[SetComp] max d" << fNoiseWidth
588 << maxd <<
" at " << maxi;
590 int32_t val = maxi - fNoiseMargin;
591 if (val < 0) val = 0;
592 rocVthrComp[roc] = val;
593 LOG(logDEBUG) <<
"set VthrComp to " << val;
597 TH1D *hsum =
bookTH1D(
"VthrCompSettings",
"VthrComp per ROC", nRocs, 0., nRocs);
598 setTitles(hsum,
"ROC",
"VthrComp [DAC]");
601 hsum->SetMaximum(256);
606 for (
int roc = 0; roc < nRocs; ++roc) {
608 fApi->
setDAC(
"VthrComp", rocVthrComp[roc], roc);
610 LOG(logINFO) <<
"ROC " << setw(2) << roc
611 <<
" VthrComp " << setw(3) << rocVthrComp[roc];
612 hsum->Fill(roc, rocVthrComp[roc]);
619 LOG(logINFO) <<
"PixTestPretest::setVthrCompId() done";
625 void PixTestPretest::setCalDel() {
626 uint16_t FLAGS = FLAG_FORCE_SERIAL | FLAG_FORCE_MASKED;
631 banner(Form(
"PixTestPretest::setCalDel()"));
636 if (
fPIX[0].first > -1) {
640 LOG(logWARNING) <<
"PreTest: no pixel defined, return";
649 string DacName =
"caldel";
653 vector<pair<uint8_t, vector<pixel> > > results;
660 LOG(logCRITICAL) <<
"problem with readout: "<< e.what() <<
" missing " << e.numberMissing <<
" events";
662 if (e.numberMissing > 10) done =
true;
664 LOG(logCRITICAL) <<
"pXar execption: "<< e.what();
667 done = (cnt>5) || done;
674 for (
int iroc = 0; iroc < nRocs; ++iroc) {
677 Form(
"NhitsVs%s_c%d_r%d_C%d", DacName.c_str(),
fPIX[0].first,
fPIX[0].second,
fId2Idx[iroc]),
680 setTitles(h1, Form(
"%s [DAC]", DacName.c_str() ),
"readouts");
685 TH1D *hsum =
bookTH1D(
"CalDelSettings",
"CalDel per ROC;ROC;CalDel [DAC]", 16, 0., 16.);
688 hsum->SetMaximum(256);
696 for (
size_t i = 0; i < results.size(); ++i) {
697 int caldel = results[i].first;
698 vector<pixel> vpix = results[i].second;
700 for (
size_t ipx = 0; ipx < vpix.size(); ++ipx) {
701 uint32_t roc = vpix.at(ipx).roc();
704 && vpix[ipx].column() ==
fPIX[0].first
705 && vpix[ipx].row() ==
fPIX[0].second
708 int nn = (int)vpix.at(ipx).value();
712 i0[fId2Idx[roc]] = caldel;
717 h1 = hsts.at(fId2Idx[roc]);
718 h1->Fill(caldel, nn);
726 for (
int roc = 0; roc < nRocs; ++roc) {
733 for (
int roc = 0; roc < nRocs; ++roc) {
740 <<
": eff plateau from " << setw(3) << i0[
fId2Idx[roc]]
741 <<
" to " << setw(3) << i9[
fId2Idx[roc]]
742 <<
": set CalDel to " << i2;
754 void PixTestPretest::programROC() {
758 banner(Form(
"PixTestPretest::programROC() "));
761 unsigned int nRocs = rocIds.size();
762 TH1D *h1 =
bookTH1D(
"programROC",
"#Delta(Iana) vs ROC", nRocs, 0., nRocs);
765 vector<int> vanaStart;
766 for (
unsigned int iroc = 0; iroc < nRocs; ++iroc) {
776 string result(
"ROCs");
778 for (
unsigned int iroc = 0; iroc < rocIds.size(); ++iroc){
779 fApi->
setDAC(
"vana", vanaStart[iroc], rocIds[iroc]);
784 result += Form(
" %d", rocIds[iroc]);
787 h1->SetBinContent(iroc+1, dA);
792 result +=
" cannot be programmed! Error!";
795 result +=
" are all programmable";
799 string dIaString(
"");
800 for (
unsigned int i = 0; i < nRocs; ++i) {
801 dIaString += Form(
" %3.1f", h1->GetBinContent(i+1));
804 LOG(logINFO) <<
"PixTestPretest::programROC() done: " << result;
805 LOG(logINFO) <<
"IA differences per ROC: " << dIaString;
817 void PixTestPretest::findWorkingPixel() {
822 banner(Form(
"PixTestPretest::findWorkingPixel()"));
825 vector<pair<int, int> > pixelList;
826 pixelList.push_back(make_pair(12,22));
827 pixelList.push_back(make_pair(5,5));
828 pixelList.push_back(make_pair(15,26));
829 pixelList.push_back(make_pair(20,32));
830 pixelList.push_back(make_pair(25,36));
831 pixelList.push_back(make_pair(30,42));
832 pixelList.push_back(make_pair(35,50));
833 pixelList.push_back(make_pair(40,60));
834 pixelList.push_back(make_pair(45,70));
835 pixelList.push_back(make_pair(50,75));
840 uint16_t FLAGS = FLAG_FORCE_MASKED;
844 map<string, TH2D*> maps;
846 bool gofishing(
false);
847 vector<pair<uint8_t, pair<uint8_t, vector<pixel> > > > rresults;
849 for (
unsigned int ifwp = 0; ifwp < pixelList.size(); ++ifwp) {
851 ic = pixelList[ifwp].first;
852 ir = pixelList[ifwp].second;
856 for (
unsigned int iroc = 0; iroc < rocIds.size(); ++iroc) {
857 h2 =
bookTH2D(Form(
"fwp_c%d_r%d_C%d", ic, ir, rocIds[iroc]),
858 Form(
"fwp_c%d_r%d_C%d", ic, ir, rocIds[iroc]),
859 256, 0., 256., 256, 0., 256.);
863 maps.insert(make_pair(Form(
"fwp_c%d_r%d_C%d", ic, ir, rocIds[iroc]), h2));
870 LOG(logCRITICAL) <<
"pXar execption: "<< e.what();
876 if (gofishing)
continue;
879 for (
unsigned i = 0; i < rresults.size(); ++i) {
880 pair<uint8_t, pair<uint8_t, vector<pixel> > > v = rresults[i];
882 pair<uint8_t, vector<pixel> > w = v.second;
884 vector<pixel> wpix = w.second;
885 for (
unsigned ipix = 0; ipix < wpix.size(); ++ipix) {
886 hname = Form(
"fwp_c%d_r%d_C%d", ic, ir, rocIds[wpix[ipix].roc()]);
887 if (maps.count(hname) > 0) {
888 maps[hname]->Fill(idac1, idac2, wpix[ipix].value());
890 LOG(logDEBUG) <<
"bad pixel address decoded: " << hname <<
", skipping";
896 bool okVthrComp(
false), okCalDel(
false);
897 bool okAllRocs(
true);
898 for (
unsigned int iroc = 0; iroc < rocIds.size(); ++iroc) {
899 okVthrComp = okCalDel =
false;
900 hname = Form(
"fwp_c%d_r%d_C%d", ic, ir, rocIds[iroc]);
906 TH1D *hy = h2->ProjectionY(
"_py", 5, h2->GetNbinsX());
907 double vcthrMax = hy->GetMaximum();
908 double bottom = hy->FindFirstBinAbove(0.5*vcthrMax);
909 double top = hy->FindLastBinAbove(0.5*vcthrMax);
910 double vthrComp = top - 50;
912 if (vthrComp > bottom) {
916 TH1D *hx = h2->ProjectionX(
"_px", vthrComp, vthrComp);
917 double cdMax = hx->GetMaximum();
918 double cdFirst = hx->GetBinLowEdge(hx->FindFirstBinAbove(0.5*cdMax));
919 double cdLast = hx->GetBinLowEdge(hx->FindLastBinAbove(0.5*cdMax));
921 if (cdLast - cdFirst > 30) {
925 if (!okVthrComp || !okCalDel) {
927 LOG(logINFO) << hname <<
" does not pass: vthrComp = " << vthrComp <<
" Delta(CalDel) = " << cdLast - cdFirst <<
", trying another";
930 LOG(logDEBUG) << hname <<
" OK, with vthrComp = " << vthrComp <<
" and Delta(CalDel) = " << cdLast - cdFirst;
934 for (
unsigned int iroc = 0; iroc < rocIds.size(); ++iroc) {
935 string name = Form(
"fwp_c%d_r%d_C%d", ic, ir, rocIds[iroc]);
936 TH2D *h = maps[name];
944 for (map<string, TH2D*>::iterator il = maps.begin(); il != maps.end(); ++il) {
951 LOG(logINFO) <<
"Found working pixel in all ROCs: col/row = " << ic <<
"/" << ir;
953 fPIX.push_back(make_pair(ic, ir));
std::map< TH1 *, std::string > fHistOptions
options can be stored with each histogram
bool setDAC(std::string dacName, uint8_t dacValue, uint8_t rocI2C)
std::vector< std::pair< int, int > > fPIX
range of enabled pixels for time-consuming tests
void testPixel(uint8_t column, uint8_t row, bool enable)
std::vector< std::pair< std::string, std::string > > fParameters
the parameters of this test
void maskAllPixels(bool mask, uint8_t rocid)
void clearSelectedPixels()
clear selected pixel list
TDirectory * fDirectory
where the root histograms will end up
std::vector< std::pair< uint8_t, std::vector< pixel > > > getEfficiencyVsDAC(std::string dacName, uint8_t dacMin, uint8_t dacMax, uint16_t flags, uint16_t nTriggers)
void restoreDacs(bool verbose=false)
restore all DACs
void addSelectedPixels(std::string sval)
add a selected pixel to the internal parameter list
std::vector< uint8_t > getEnabledRocIDs()
void testAllPixels(bool enable)
std::list< TH1 * >::iterator fDisplayedHist
pointer to the histogram currently displayed
TH1D * bookTH1D(std::string sname, std::string title, int nbins, double xmin, double xmax)
book a TH1D, adding version information to the name and title
virtual std::string getHistOption(TH1 *)
get the hist display options (if stored in fHistOptions)
void cacheDacs(bool verbose=false)
cache all DACs
std::list< TH1 * > fHistList
list of histograms available in PixTab::next and PixTab::previous
void setTitles(TH1 *h, const char *sx, const char *sy, float size=0.05, float xoff=1.1, float yoff=1.1, float lsize=0.05, int font=42)
utility to set histogram titles
std::vector< std::pair< uint8_t, std::pair< uint8_t, std::vector< pixel > > > > getEfficiencyVsDACDAC(std::string dac1name, uint8_t dac1min, uint8_t dac1max, std::string dac2name, uint8_t dac2min, uint8_t dac2max, uint16_t flags, uint16_t nTriggers)
bool selectedRoc(int id)
is ROC ID selected?
void saveDacs()
save DACs to file
TH2D * bookTH2D(std::string sname, std::string title, int nbinsx, double xmin, double xmax, int nbinsy, double ymin, double max)
book a TH2D, adding version information to the name and title
void maskPixel(uint8_t column, uint8_t row, bool mask)
void update()
signal to PixTab to update the canvas
uint8_t getDAC(size_t rocId, std::string dacName)
void setToolTips()
implement this to provide updated tool tips if the user changes test parameters
pxar::pxarCore * fApi
pointer to the API
void doTest()
function connected to "DoTest" button of PixTab
std::map< int, int > fId2Idx
map the ROC ID onto the (results vector) index of the ROC
void init()
sets all test parameters
virtual bool setParameter(std::string parName, std::string sval)
set the string value of a parameter
void runCommand(std::string)
allow execution of any button in the test
int getIdFromIdx(int idx)
provide the mapping between ROC ID and index