pxar
All Classes Namespaces Functions Variables Typedefs Friends
PixTestPretest.cc
1 #include <iostream>
2 #include <stdlib.h>
3 #include <algorithm>
4 
5 #include <TStyle.h>
6 #include <TMarker.h>
7 #include <TStopwatch.h>
8 
9 #include "PixTestPretest.hh"
10 #include "log.h"
11 #include "helper.h"
12 
13 using namespace std;
14 using namespace pxar;
15 
16 ClassImp(PixTestPretest)
17 
18 // ----------------------------------------------------------------------
19 PixTestPretest::PixTestPretest( PixSetup *a, std::string name) :
20 PixTest(a, name),
21  fTargetIa(-1), fNoiseWidth(22), fNoiseMargin(10),
22  fParNtrig(-1),
23  fParVcal(200),
24  fParDeltaVthrComp(-50),
25  fParFracCalDel(0.5) {
26  PixTest::init();
27  init();
28 }
29 
30 // ----------------------------------------------------------------------
31 PixTestPretest::PixTestPretest() : PixTest() {
32  // LOG(logINFO) << "PixTestPretest ctor()";
33 }
34 
35 
36 // ----------------------------------------------------------------------
37 bool PixTestPretest::setParameter(string parName, string sval) {
38  bool found(false);
39  string str1, str2;
40  string::size_type s1;
41  int pixc, pixr;
42  std::transform(parName.begin(), parName.end(), parName.begin(), ::tolower);
43  for (unsigned int i = 0; i < fParameters.size(); ++i) {
44  if (fParameters[i].first == parName) {
45  found = true;
46  sval.erase(remove(sval.begin(), sval.end(), ' '), sval.end());
47 
48  if (!parName.compare("targetia")) {
49  fTargetIa = atoi(sval.c_str()); // [mA/ROC]
50  }
51 
52  if (!parName.compare("noisewidth")) {
53  fNoiseWidth = atoi(sval.c_str());
54  }
55 
56  if (!parName.compare("noisemargin")) {
57  fNoiseMargin = atoi(sval.c_str()); // safety margin below noise
58  }
59 
60  if (!parName.compare("ntrig") ) {
61  fParNtrig = atoi(sval.c_str() );
62  }
63 
64  if (!parName.compare("vcal") ) {
65  fParVcal = atoi(sval.c_str() );
66  }
67 
68  if (!parName.compare("deltavthrcomp") ) {
69  fParDeltaVthrComp = atoi(sval.c_str() );
70  }
71 
72  if (!parName.compare("fraccaldel") ) {
73  fParFracCalDel = atof(sval.c_str() );
74  }
75 
76  if (!parName.compare("pix") || !parName.compare("pix1") ) {
77  s1 = sval.find(",");
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) );
85  addSelectedPixels(sval);
86  } else {
88  addSelectedPixels("-1,-1");
89  LOG(logDEBUG) << " clear fPIX: " << fPIX.size();
90  }
91 
92  }
93  break;
94  }
95  }
96  return found;
97 }
98 
99 // ----------------------------------------------------------------------
100 void PixTestPretest::init() {
101  setToolTips();
102  fDirectory = gFile->GetDirectory(fName.c_str());
103  if( !fDirectory ) {
104  fDirectory = gFile->mkdir(fName.c_str());
105  }
106  fDirectory->cd();
107 }
108 
109 
110 // ----------------------------------------------------------------------
112  fTestTip = string( "Pretest: set Vana, VthrComp, and CalDel")
113  + string("\ntune PH into ADC range using VOffsetRO and VIref_ADC")
114  ;
115  fSummaryTip = string("summary plot to be implemented");
116 }
117 
118 // ----------------------------------------------------------------------
119 void PixTestPretest::bookHist(string name) {
120  fDirectory->cd();
121 
122  LOG(logDEBUG) << "nothing done with " << name;
123 }
124 
125 // ----------------------------------------------------------------------
126 PixTestPretest::~PixTestPretest() {
127  LOG(logDEBUG) << "PixTestPretest dtor";
128 }
129 
130 // ----------------------------------------------------------------------
132 
133  TStopwatch t;
134 
135  fDirectory->cd();
136  PixTest::update();
137  bigBanner(Form("PixTestPretest::doTest()"));
138 
139  programROC();
140  TH1 *h1 = (*fDisplayedHist);
141  h1->Draw(getHistOption(h1).c_str());
142  PixTest::update();
143 
144  if (fProblem) {
145  bigBanner("ERROR: some ROCs are not programmable; stop");
146  return;
147  }
148 
149  setVana();
150  h1 = (*fDisplayedHist);
151  h1->Draw(getHistOption(h1).c_str());
152  PixTest::update();
153 
154  findWorkingPixel();
155  h1 = (*fDisplayedHist);
156  h1->Draw(getHistOption(h1).c_str());
157  PixTest::update();
158 
159  setVthrCompCalDel();
160  h1 = (*fDisplayedHist);
161  h1->Draw(getHistOption(h1).c_str());
162  PixTest::update();
163 
164  // -- save DACs!
165  saveDacs();
166 
167  int seconds = t.RealTime();
168  LOG(logINFO) << "PixTestPretest::doTest() done, duration: " << seconds << " seconds";
169 }
170 
171 // ----------------------------------------------------------------------
172 void PixTestPretest::runCommand(std::string command) {
173  std::transform(command.begin(), command.end(), command.begin(), ::tolower);
174  LOG(logDEBUG) << "running command: " << command;
175  if (!command.compare("programroc")) {
176  programROC();
177  return;
178  }
179  if (!command.compare("setcaldel")) {
180  setCalDel();
181  return;
182  }
183  if (!command.compare("savedacs")) {
184  saveDacs();
185  return;
186  }
187  if (!command.compare("setvana")) {
188  setVana();
189  return;
190  }
191  if (!command.compare("findworkingpixel")) {
192  findWorkingPixel();
193  return;
194  }
195  if (!command.compare("setvthrcompcaldel")) {
196  setVthrCompCalDel();
197  return;
198  }
199  if (!command.compare("setvthrcompid")) {
200  setVthrCompId();
201  return;
202  }
203 
204  LOG(logDEBUG) << "did not find command ->" << command << "<-";
205 }
206 
207 
208 // ----------------------------------------------------------------------
209 void PixTestPretest::setVana() {
210  cacheDacs();
211  fDirectory->cd();
212  PixTest::update();
213  banner(Form("PixTestPretest::setVana() target Ia = %d mA/ROC", fTargetIa));
214 
215  fApi->_dut->testAllPixels(false);
216 
217  vector<uint8_t> vanaStart;
218  vector<double> rocIana;
219 
220  // -- cache setting and switch off all(!) ROCs
221  int nRocs = fApi->_dut->getNRocs();
222  for (int iroc = 0; iroc < nRocs; ++iroc) {
223  vanaStart.push_back(fApi->_dut->getDAC(iroc, "vana"));
224  rocIana.push_back(0.);
225  fApi->setDAC("vana", 0, iroc);
226  }
227 
228  double i016 = fApi->getTBia()*1E3;
229 
230  // FIXME this should not be a stopwatch, but a delay
231  TStopwatch sw;
232  sw.Start(kTRUE); // reset
233  do {
234  sw.Start(kFALSE); // continue
235  i016 = fApi->getTBia()*1E3;
236  } while (sw.RealTime() < 0.1);
237 
238  // subtract one ROC to get the offset from the other Rocs (on average):
239  double i015 = (nRocs-1) * i016 / nRocs; // = 0 for single chip tests
240  LOG(logDEBUG) << "offset current from other " << nRocs-1 << " ROCs is " << i015 << " mA";
241 
242  // tune per ROC:
243 
244  const double extra = 0.1; // [mA] besser zu viel als zu wenig
245  const double eps = 0.25; // [mA] convergence
246  const double slope = 6; // 255 DACs / 40 mA
247 
248  for (int roc = 0; roc < nRocs; ++roc) {
249  if (!selectedRoc(roc)) {
250  LOG(logDEBUG) << "skipping ROC idx = " << roc << " (not selected) for Vana tuning";
251  continue;
252  }
253  int vana = vanaStart[roc];
254  fApi->setDAC("vana", vana, roc); // start value
255 
256  double ia = fApi->getTBia()*1E3; // [mA], just to be sure to flush usb
257  sw.Start(kTRUE); // reset
258  do {
259  sw.Start(kFALSE); // continue
260  ia = fApi->getTBia()*1E3; // [mA]
261  } while (sw.RealTime() < 0.1);
262 
263  double diff = fTargetIa + extra - (ia - i015);
264 
265  int iter = 0;
266  LOG(logDEBUG) << "ROC " << roc << " iter " << iter
267  << " Vana " << vana
268  << " Ia " << ia-i015 << " mA";
269 
270  while (TMath::Abs(diff) > eps && iter < 11 && vana > 0 && vana < 255) {
271 
272  int stp = static_cast<int>(TMath::Abs(slope*diff));
273  if (stp == 0) stp = 1;
274  if (diff < 0) stp = -stp;
275 
276  vana += stp;
277 
278  if (vana < 0) {
279  vana = 0;
280  } else {
281  if (vana > 255) {
282  vana = 255;
283  }
284  }
285 
286  fApi->setDAC("vana", vana, roc);
287  iter++;
288 
289  sw.Start(kTRUE); // reset
290  do {
291  sw.Start(kFALSE); // continue
292  ia = fApi->getTBia()*1E3; // [mA]
293  }
294  while( sw.RealTime() < 0.1 );
295 
296  diff = fTargetIa + extra - (ia - i015);
297 
298  LOG(logDEBUG) << "ROC " << setw(2) << roc
299  << " iter " << setw(2) << iter
300  << " Vana " << setw(3) << vana
301  << " Ia " << ia-i015 << " mA";
302  } // iter
303 
304  rocIana[roc] = ia-i015; // more or less identical for all ROCS?!
305  vanaStart[roc] = vana; // remember best
306  fApi->setDAC( "vana", 0, roc ); // switch off for next ROC
307 
308  } // rocs
309 
310  TH1D *hsum = bookTH1D("VanaSettings", "Vana per ROC", nRocs, 0., nRocs);
311  setTitles(hsum, "ROC", "Vana [DAC]");
312  hsum->SetStats(0);
313  hsum->SetMinimum(0);
314  hsum->SetMaximum(256);
315  fHistList.push_back(hsum);
316 
317  TH1D *hcurr = bookTH1D("Iana", "Iana per ROC", nRocs, 0., nRocs);
318  setTitles(hcurr, "ROC", "Vana [DAC]");
319  hcurr->SetStats(0); // no stats
320  hcurr->SetMinimum(0);
321  hcurr->SetMaximum(30.0);
322  fHistList.push_back(hcurr);
323 
324 
325  restoreDacs();
326  for (int roc = 0; roc < nRocs; ++roc) {
327  // -- reset all ROCs to optimum or cached value
328  fApi->setDAC( "vana", vanaStart[roc], roc );
329  LOG(logDEBUG) << "ROC " << setw(2) << roc << " Vana " << setw(3) << int(vanaStart[roc]);
330  // -- histogramming only for those ROCs that were selected
331  if (!selectedRoc(roc)) continue;
332  hsum->Fill(roc, vanaStart[roc] );
333  hcurr->Fill(roc, rocIana[roc]);
334  }
335 
336  double ia16 = fApi->getTBia()*1E3; // [mA]
337 
338  sw.Start(kTRUE); // reset
339  do {
340  sw.Start(kFALSE); // continue
341  ia16 = fApi->getTBia()*1E3; // [mA]
342  }
343  while( sw.RealTime() < 0.1 );
344 
345 
346  hsum->Draw();
347  fDisplayedHist = find(fHistList.begin(), fHistList.end(), hsum);
348  PixTest::update();
349 
350  LOG(logINFO) << "PixTestPretest::setVana() done, Module Ia " << ia16 << " mA = " << ia16/nRocs << " mA/ROC";
351 
352 }
353 
354 
355 // ----------------------------------------------------------------------
356 void PixTestPretest::setVthrCompCalDel() {
357  uint16_t FLAGS = FLAG_FORCE_MASKED;
358 
359  cacheDacs();
360  fDirectory->cd();
361  PixTest::update();
362  banner(Form("PixTestPretest::setVthrCompCalDel()"));
363 
364  string name("pretestVthrCompCalDel");
365 
366  fApi->setDAC("CtrlReg", 0);
367  fApi->setDAC("Vcal", 250);
368 
369  fApi->_dut->testAllPixels(false);
370  fApi->_dut->maskAllPixels(true);
371 
372  vector<uint8_t> rocIds = fApi->_dut->getEnabledRocIDs();
373 
374  TH1D *h1(0);
375  h1 = bookTH1D(Form("pretestCalDel"), Form("pretestCalDel"), rocIds.size(), 0., rocIds.size());
376  h1->SetMinimum(0.);
377  h1->SetDirectory(fDirectory);
378  setTitles(h1, "ROC", "CalDel DAC");
379 
380  TH2D *h2(0);
381 
382  vector<int> calDel(rocIds.size(), -1);
383  vector<int> vthrComp(rocIds.size(), -1);
384  vector<int> calDelE(rocIds.size(), -1);
385 
386  int ip = 0;
387 
388  fApi->_dut->testPixel(fPIX[ip].first, fPIX[ip].second, true);
389  fApi->_dut->maskPixel(fPIX[ip].first, fPIX[ip].second, false);
390 
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.);
396  fHistOptions.insert(make_pair(h2, "colz"));
397  maps.insert(make_pair(rocIds[iroc], h2));
398  h2->SetMinimum(0.);
399  h2->SetMaximum(fParNtrig);
400  h2->SetDirectory(fDirectory);
401  setTitles(h2, "CalDel", "VthrComp");
402  }
403 
404  bool done = false;
405  vector<pair<uint8_t, pair<uint8_t, vector<pixel> > > > rresults;
406  while (!done) {
407  rresults.clear();
408  int cnt(0);
409  try{
410  rresults = fApi->getEfficiencyVsDACDAC("caldel", 0, 255, "vthrcomp", 0, 180, FLAGS, fParNtrig);
411  done = true;
412  } catch(DataMissingEvent &e){
413  LOG(logCRITICAL) << "problem with readout: "<< e.what() << " missing " << e.numberMissing << " events";
414  ++cnt;
415  if (e.numberMissing > 10) done = true;
416  } catch(pxarException &e) {
417  LOG(logCRITICAL) << "pXar execption: "<< e.what();
418  ++cnt;
419  }
420  done = (cnt>5) || done;
421  }
422 
423  fApi->_dut->testPixel(fPIX[ip].first, fPIX[ip].second, false);
424  fApi->_dut->maskPixel(fPIX[ip].first, fPIX[ip].second, true);
425 
426  for (unsigned i = 0; i < rresults.size(); ++i) {
427  pair<uint8_t, pair<uint8_t, vector<pixel> > > v = rresults[i];
428  int idac1 = v.first;
429  pair<uint8_t, vector<pixel> > w = v.second;
430  int idac2 = w.first;
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());
434  }
435  }
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);
442  delete hy;
443 
444  if (fParDeltaVthrComp>0) {
445  vthrComp[iroc] = bottom + fParDeltaVthrComp;
446  } else {
447  vthrComp[iroc] = top + fParDeltaVthrComp;
448  }
449 
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);
464  delete h0;
465 
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];
469 
470  h2->Draw(getHistOption(h2).c_str());
471  PixTest::update();
472  pxar::mDelay(500);
473 
474  fHistList.push_back(h2);
475  }
476 
477  fHistList.push_back(h1);
478 
479  fDisplayedHist = find(fHistList.begin(), fHistList.end(), h2);
480  PixTest::update();
481 
482  restoreDacs();
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]);
488  } else {
489  caldelString += Form(" _%4d", fApi->_dut->getDAC(rocIds[iroc], "caldel"));
490  }
491  fApi->setDAC("VthrComp", vthrComp[iroc], rocIds[iroc]);
492  vthrcompString += Form(" %4d", vthrComp[iroc]);
493  }
494 
495  // -- summary printout
496  LOG(logINFO) << "PixTestPretest::setVthrCompCalDel() done";
497  LOG(logINFO) << "CalDel: " << caldelString;
498  LOG(logINFO) << "VthrComp: " << vthrcompString;
499 
500 }
501 
502 
503 // ----------------------------------------------------------------------
504 void PixTestPretest::setVthrCompId() {
505 
506  cacheDacs();
507  fDirectory->cd();
508  PixTest::update();
509  banner(Form("PixTestPretest::setVthrCompId()"));
510 
511  vector<TH1D*> hsts;
512  TH1D *h1(0);
513 
514  int nRocs = fApi->_dut->getNRocs();
515 
516  for (int roc = 0; roc < nRocs; ++roc) {
517  if (!selectedRoc(roc)) continue;
518  h1 = bookTH1D(Form("Id_vs_VthrComp_C%d", int(roc)),
519  Form("Id vs VthrComp C%d", int(roc)),
520  256, 0., 256.);
521  h1->SetMinimum(0);
522  h1->SetStats(0);
523  setTitles( h1, "VthrComp [DAC]", "ROC digital current [mA]" );
524  hsts.push_back(h1);
525  fHistList.push_back(h1);
526  }
527 
528  fApi->_dut->testAllPixels(true); // enable all pix: more noise
529 
530  for (int roc = 0; roc < nRocs; ++roc) {
531  fApi->setDAC("Vsf", 33, roc); // small
532  fApi->setDAC("VthrComp", 0, roc); // off
533  }
534 
535  double i016 = fApi->getTBid()*1E3;
536  TStopwatch sw;
537  sw.Start(kTRUE); // reset
538  do {
539  sw.Start(kFALSE); // continue
540  i016 = fApi->getTBid()*1E3;
541  }
542  while( sw.RealTime() < 0.1 ); // discharge time
543 
544  double i015 = (nRocs-1) * i016 / nRocs; // = 0 for single chip tests
545 
546  LOG(logINFO) << "offset current from other " << nRocs-1 << " ROCs is "
547  << i015 << " mA";
548 
549  TH1D *hid(0);
550 
551  // loope over ROCs:
552 
553  vector<int> rocVthrComp(nRocs, -1);
554  for (int roc = 0; roc < nRocs; ++roc) {
555  if (!selectedRoc(roc)) continue;
556 
557  LOG(logDEBUG) << "ROC " << setw(2) << roc;
558 
559  hid = hsts[roc];
560 
561  for (size_t idac = 0; idac < 256; ++idac) {
562  fApi->setDAC("VthrComp", idac, roc);
563  // delay?
564  hid->Fill(idac, fApi->getTBid()*1E3 - i015);
565  }
566 
567  fApi->setDAC("VthrComp", 0, roc); // switch off
568 
569  if (hid) hid->Draw();
570  PixTest::update();
571 
572  // analyze:
573 
574  LOG(logDEBUG) << "current peak " << hid->GetMaximum()
575  << " mA at DAC " << hid->GetMaximumBin();
576 
577  double maxd = 0;
578  int maxi = 0;
579  for (int i = 1; i <= 256-fNoiseWidth; ++i) { // histo bin counting starts at 1
580  double ni = hid->GetBinContent(i);
581  double d = hid->GetBinContent(i+fNoiseWidth) - ni;
582  if (d > maxd) {
583  maxd = d;
584  maxi = i-1;
585  }
586  }
587  LOG(logDEBUG) << "[SetComp] max d" << fNoiseWidth
588  << maxd << " at " << maxi;
589 
590  int32_t val = maxi - fNoiseMargin; // safety
591  if (val < 0) val = 0;
592  rocVthrComp[roc] = val;
593  LOG(logDEBUG) << "set VthrComp to " << val;
594 
595  } // rocs
596 
597  TH1D *hsum = bookTH1D("VthrCompSettings", "VthrComp per ROC", nRocs, 0., nRocs);
598  setTitles(hsum, "ROC", "VthrComp [DAC]");
599  hsum->SetStats(0); // no stats
600  hsum->SetMinimum(0);
601  hsum->SetMaximum(256);
602  fHistList.push_back(hsum);
603 
604 
605  restoreDacs();
606  for (int roc = 0; roc < nRocs; ++roc) {
607  // -- (re)set all
608  fApi->setDAC("VthrComp", rocVthrComp[roc], roc);
609  // -- report on/histogram only selected ROCs
610  LOG(logINFO) << "ROC " << setw(2) << roc
611  << " VthrComp " << setw(3) << rocVthrComp[roc];
612  hsum->Fill(roc, rocVthrComp[roc]);
613  }
614 
615  hsum->Draw();
616  fDisplayedHist = find(fHistList.begin(), fHistList.end(), hsum);
617  PixTest::update();
618 
619  LOG(logINFO) << "PixTestPretest::setVthrCompId() done";
620 
621 }
622 
623 
624 // ----------------------------------------------------------------------
625 void PixTestPretest::setCalDel() {
626  uint16_t FLAGS = FLAG_FORCE_SERIAL | FLAG_FORCE_MASKED; // required for manual loop over ROCs
627 
628  cacheDacs();
629  fDirectory->cd();
630  PixTest::update();
631  banner(Form("PixTestPretest::setCalDel()"));
632 
633  fApi->_dut->testAllPixels(false);
634  fApi->_dut->maskAllPixels(true);
635 
636  if (fPIX[0].first > -1) {
637  fApi->_dut->testPixel(fPIX[0].first, fPIX[0].second, true);
638  fApi->_dut->maskPixel(fPIX[0].first, fPIX[0].second, false);
639  } else {
640  LOG(logWARNING) << "PreTest: no pixel defined, return";
641  return;
642  }
643 
644  // set maximum pulse (minimal time walk):
645 
646  fApi->setDAC("Vcal", 250);
647  fApi->setDAC("CtrlReg", 4);
648 
649  string DacName = "caldel";
650 
651  // measure:
652  bool done = false;
653  vector<pair<uint8_t, vector<pixel> > > results;
654  int cnt(0);
655  while (!done) {
656  try{
657  results = fApi->getEfficiencyVsDAC(DacName, 0, 250, FLAGS, fParNtrig);
658  done = true;
659  } catch(DataMissingEvent &e){
660  LOG(logCRITICAL) << "problem with readout: "<< e.what() << " missing " << e.numberMissing << " events";
661  ++cnt;
662  if (e.numberMissing > 10) done = true;
663  } catch(pxarException &e) {
664  LOG(logCRITICAL) << "pXar execption: "<< e.what();
665  ++cnt;
666  }
667  done = (cnt>5) || done;
668  }
669 
670  // histos:
671  vector<TH1D*> hsts;
672  TH1D *h1(0);
673  int nRocs = fApi->_dut->getNEnabledRocs();
674  for (int iroc = 0; iroc < nRocs; ++iroc) {
675  if (!selectedRoc(iroc)) continue;
676  h1 = bookTH1D(Form("NhitsVs%s_c%d_r%d_C%d", DacName.c_str(), fPIX[0].first, fPIX[0].second, fId2Idx[iroc]),
677  Form("NhitsVs%s_c%d_r%d_C%d", DacName.c_str(), fPIX[0].first, fPIX[0].second, fId2Idx[iroc]),
678  256, 0., 256.);
679  h1->SetMinimum(0);
680  setTitles(h1, Form( "%s [DAC]", DacName.c_str() ), "readouts");
681  fHistList.push_back(h1);
682  hsts.push_back(h1);
683  }
684 
685  TH1D *hsum = bookTH1D( "CalDelSettings", "CalDel per ROC;ROC;CalDel [DAC]", 16, 0., 16.);
686  hsum->SetStats(0); // no stats
687  hsum->SetMinimum(0);
688  hsum->SetMaximum(256);
689  fHistList.push_back(hsum);
690 
691  // FIXME this is so bad
692  int i0[35] = {0};
693  int i9[35] = {0};
694  int nm[35] = {0};
695 
696  for (size_t i = 0; i < results.size(); ++i) {
697  int caldel = results[i].first;
698  vector<pixel> vpix = results[i].second;
699 
700  for (size_t ipx = 0; ipx < vpix.size(); ++ipx) {
701  uint32_t roc = vpix.at(ipx).roc();
702 
703  if (fId2Idx[roc] < nRocs
704  && vpix[ipx].column() == fPIX[0].first
705  && vpix[ipx].row() == fPIX[0].second
706  ) {
707 
708  int nn = (int)vpix.at(ipx).value();
709 
710  if (nn > nm[fId2Idx[roc]]) {
711  nm[fId2Idx[roc]] = nn;
712  i0[fId2Idx[roc]] = caldel; // begin of plateau
713  }
714  if (nn == nm[fId2Idx[roc]] )
715  i9[fId2Idx[roc]] = caldel; // end of plateau
716 
717  h1 = hsts.at(fId2Idx[roc]);
718  h1->Fill(caldel, nn);
719 
720  } // valid
721 
722  } // pixels and rocs
723 
724  } // caldel vals
725 
726  for (int roc = 0; roc < nRocs; ++roc) {
727  hsts[fId2Idx[roc]]->Draw();
728  PixTest::update();
729  }
730 
731  // set CalDel:
732  restoreDacs();
733  for (int roc = 0; roc < nRocs; ++roc) {
734  if (i9[fId2Idx[roc]] > 0 ) {
735 
736  int i2 = i0[fId2Idx[roc]] + (i9[fId2Idx[roc]]-i0[fId2Idx[roc]])/4;
737  fApi->setDAC(DacName, i2, getIdFromIdx(roc));
738 
739  LOG(logINFO) << "ROC " << setw(2) << getIdFromIdx(roc)
740  << ": eff plateau from " << setw(3) << i0[fId2Idx[roc]]
741  << " to " << setw(3) << i9[fId2Idx[roc]]
742  << ": set CalDel to " << i2;
743 
744  hsum->Fill(roc, i2);
745  }
746  } // rocs
747 
748  hsum->Draw();
749  PixTest::update();
750  fDisplayedHist = find(fHistList.begin(), fHistList.end(), hsum);
751 }
752 
753 // ----------------------------------------------------------------------
754 void PixTestPretest::programROC() {
755  cacheDacs();
756  fDirectory->cd();
757  PixTest::update();
758  banner(Form("PixTestPretest::programROC() "));
759 
760  vector<uint8_t> rocIds = fApi->_dut->getEnabledRocIDs();
761  unsigned int nRocs = rocIds.size();
762  TH1D *h1 = bookTH1D("programROC", "#Delta(Iana) vs ROC", nRocs, 0., nRocs);
763  fHistList.push_back(h1);
764 
765  vector<int> vanaStart;
766  for (unsigned int iroc = 0; iroc < nRocs; ++iroc) {
767  vanaStart.push_back(fApi->_dut->getDAC(rocIds[iroc], "vana"));
768  fApi->setDAC("vana", 0, rocIds[iroc]);
769  }
770 
771  pxar::mDelay(2000);
772  double iA0 = fApi->getTBia()*1E3;
773  // cout << "iA0 = " << iA0 << endl;
774 
775  double iA, dA;
776  string result("ROCs");
777  bool problem(false);
778  for (unsigned int iroc = 0; iroc < rocIds.size(); ++iroc){
779  fApi->setDAC("vana", vanaStart[iroc], rocIds[iroc]);
780  pxar::mDelay(1000);
781  iA = fApi->getTBia()*1E3;
782  dA = iA - iA0;
783  if (dA < 5) {
784  result += Form(" %d", rocIds[iroc]);
785  problem = true;
786  }
787  h1->SetBinContent(iroc+1, dA);
788  fApi->setDAC("vana", 0, rocIds[iroc]);
789  }
790 
791  if (problem) {
792  result += " cannot be programmed! Error!";
793  fProblem = true;
794  } else {
795  result += " are all programmable";
796  }
797 
798  // -- summary printout
799  string dIaString("");
800  for (unsigned int i = 0; i < nRocs; ++i) {
801  dIaString += Form(" %3.1f", h1->GetBinContent(i+1));
802  }
803 
804  LOG(logINFO) << "PixTestPretest::programROC() done: " << result;
805  LOG(logINFO) << "IA differences per ROC: " << dIaString;
806 
807  h1 = (TH1D*)(fHistList.back());
808  h1->Draw(getHistOption(h1).c_str());
809  fDisplayedHist = find(fHistList.begin(), fHistList.end(), h1);
810  PixTest::update();
811 
812  restoreDacs();
813 }
814 
815 
816 // ----------------------------------------------------------------------
817 void PixTestPretest::findWorkingPixel() {
818 
819  cacheDacs();
820  fDirectory->cd();
821  PixTest::update();
822  banner(Form("PixTestPretest::findWorkingPixel()"));
823 
824 
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));
836 
837  fApi->_dut->testAllPixels(false);
838  fApi->_dut->maskAllPixels(true);
839 
840  uint16_t FLAGS = FLAG_FORCE_MASKED;
841 
842  vector<uint8_t> rocIds = fApi->_dut->getEnabledRocIDs();
843  TH2D *h2(0);
844  map<string, TH2D*> maps;
845 
846  bool gofishing(false);
847  vector<pair<uint8_t, pair<uint8_t, vector<pixel> > > > rresults;
848  int ic(-1), ir(-1);
849  for (unsigned int ifwp = 0; ifwp < pixelList.size(); ++ifwp) {
850  gofishing = false;
851  ic = pixelList[ifwp].first;
852  ir = pixelList[ifwp].second;
853  fApi->_dut->testPixel(ic, ir, true);
854  fApi->_dut->maskPixel(ic, ir, false);
855 
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.);
860  h2->SetMinimum(0.);
861  h2->SetDirectory(fDirectory);
862  fHistOptions.insert(make_pair(h2, "colz"));
863  maps.insert(make_pair(Form("fwp_c%d_r%d_C%d", ic, ir, rocIds[iroc]), h2));
864  }
865 
866  rresults.clear();
867  try{
868  rresults = fApi->getEfficiencyVsDACDAC("caldel", 0, 255, "vthrcomp", 0, 180, FLAGS, 5);
869  } catch(pxarException &e) {
870  LOG(logCRITICAL) << "pXar execption: "<< e.what();
871  gofishing = true;
872  }
873 
874  fApi->_dut->testPixel(ic, ir, false);
875  fApi->_dut->maskPixel(ic, ir, true);
876  if (gofishing) continue;
877 
878  string hname;
879  for (unsigned i = 0; i < rresults.size(); ++i) {
880  pair<uint8_t, pair<uint8_t, vector<pixel> > > v = rresults[i];
881  int idac1 = v.first;
882  pair<uint8_t, vector<pixel> > w = v.second;
883  int idac2 = w.first;
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());
889  } else {
890  LOG(logDEBUG) << "bad pixel address decoded: " << hname << ", skipping";
891  }
892  }
893  }
894 
895 
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]);
901  h2 = maps[hname];
902 
903  h2->Draw("colz");
904  PixTest::update();
905 
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;
911  delete hy;
912  if (vthrComp > bottom) {
913  okVthrComp = true;
914  }
915 
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));
920  delete hx;
921  if (cdLast - cdFirst > 30) {
922  okCalDel = true;
923  }
924 
925  if (!okVthrComp || !okCalDel) {
926  okAllRocs = false;
927  LOG(logINFO) << hname << " does not pass: vthrComp = " << vthrComp << " Delta(CalDel) = " << cdLast - cdFirst << ", trying another";
928  break;
929  } else{
930  LOG(logDEBUG) << hname << " OK, with vthrComp = " << vthrComp << " and Delta(CalDel) = " << cdLast - cdFirst;
931  }
932  }
933  if (okAllRocs) {
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];
937  fHistList.push_back(h);
938  h->Draw(getHistOption(h).c_str());
939  fDisplayedHist = find(fHistList.begin(), fHistList.end(), h);
940  PixTest::update();
941  }
942  break;
943  } else {
944  for (map<string, TH2D*>::iterator il = maps.begin(); il != maps.end(); ++il) {
945  delete (*il).second;
946  }
947  maps.clear();
948  }
949  }
950 
951  LOG(logINFO) << "Found working pixel in all ROCs: col/row = " << ic << "/" << ir;
953  fPIX.push_back(make_pair(ic, ir));
954  addSelectedPixels(Form("%d,%d", ic, ir));
955 
956 
957  fApi->_dut->testAllPixels(true);
958  fApi->_dut->maskAllPixels(false);
959 
960  restoreDacs();
961 
962 }
std::map< TH1 *, std::string > fHistOptions
options can be stored with each histogram
Definition: PixTest.hh:308
bool setDAC(std::string dacName, uint8_t dacValue, uint8_t rocI2C)
Definition: api.cc:546
double getTBid()
Definition: api.cc:434
std::vector< std::pair< int, int > > fPIX
range of enabled pixels for time-consuming tests
Definition: PixTest.hh:311
void testPixel(uint8_t column, uint8_t row, bool enable)
Definition: dut.cc:432
std::vector< std::pair< std::string, std::string > > fParameters
the parameters of this test
Definition: PixTest.hh:302
void maskAllPixels(bool mask, uint8_t rocid)
Definition: dut.cc:481
void clearSelectedPixels()
clear selected pixel list
Definition: PixTest.cc:498
TDirectory * fDirectory
where the root histograms will end up
Definition: PixTest.hh:306
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)
Definition: api.cc:733
void restoreDacs(bool verbose=false)
restore all DACs
Definition: PixTest.cc:771
dut * _dut
Definition: api.h:728
void addSelectedPixels(std::string sval)
add a selected pixel to the internal parameter list
Definition: PixTest.cc:480
std::vector< uint8_t > getEnabledRocIDs()
Definition: dut.cc:214
void testAllPixels(bool enable)
Definition: dut.cc:503
std::list< TH1 * >::iterator fDisplayedHist
pointer to the histogram currently displayed
Definition: PixTest.hh:309
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
Definition: PixTest.cc:895
virtual std::string getHistOption(TH1 *)
get the hist display options (if stored in fHistOptions)
Definition: PixTest.cc:941
void cacheDacs(bool verbose=false)
cache all DACs
Definition: PixTest.cc:760
std::list< TH1 * > fHistList
list of histograms available in PixTab::next and PixTab::previous
Definition: PixTest.hh:307
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
Definition: PixTest.cc:649
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)
Definition: api.cc:951
bool selectedRoc(int id)
is ROC ID selected?
Definition: PixTest.cc:879
size_t getNEnabledRocs()
Definition: dut.cc:74
void saveDacs()
save DACs to file
Definition: PixTest.cc:1511
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
Definition: PixTest.cc:903
double getTBia()
Definition: api.cc:424
void maskPixel(uint8_t column, uint8_t row, bool mask)
Definition: dut.cc:397
void update()
signal to PixTab to update the canvas
Definition: PixTest.cc:569
uint8_t getDAC(size_t rocId, std::string dacName)
Definition: dut.cc:314
void setToolTips()
implement this to provide updated tool tips if the user changes test parameters
size_t getNRocs()
Definition: dut.cc:84
pxar::pxarCore * fApi
pointer to the API
Definition: PixTest.hh:289
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
Definition: PixTest.hh:312
void init()
sets all test parameters
Definition: PixTest.cc:62
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
Definition: PixTest.cc:1114
void mDelay(uint32_t ms)
Definition: helper.h:40