// // uconn.cc - main program to read data in from an evio // event file produced by the readout of the // UConn fiber QA data acquisition crate, and // save the results in a root tree. // // authors: richard.t.jones at uconn.edu, // barnes at phys.uconn.edu // aaron.carta at uconn.edu // version: january 31, 2014 // // usage: // $ ./uconn .evt.0 // $ root -l .root // root> .L Tracer.C // root> TTree *t=tree1; // root> Tracer tr(t); // root> tr.Show(6,0,0,2); // to see event 2, channel 6 // // notes: // 1) The input is a single evio file that is assumed to // end with the extension ".evio" which is named as the // only required command line argument. // 2) The output is a root file created in the same // directory as the input file, and with the same name // with the extension ".evio" changed to ".root". This // file contains a large number of irrelevant output // histograms of obscure origin, plus one large tree // named "tree1" with the following contents. // // branch leafname description // ------------------------------------------------------- // fadc_raw fadc_raw[i][j][k] fADC250 raw time series // values (int) for sample // k=0..255, channel j=0..16 // and module i=0..1, only // filled if fADC250 is set // to raw mode. // fadc_pulse fadc_pulse[i][j][k] fADC250 raw time series // values (int) for sample // k=0..255, channel j=0..16 // and module i=0..1, only // filled if fADC250 is set // to pulse window mode. // nhit_tdc nhit_tdc number of tdc hits (int) // maximum value 64. // tdc_ch tdc_ch[i] tdc channel (int) of hit // i=0..nhit_tdc-1 // tdc_time tdc_time[i] tdc time (int) of hit // i=0..nhit_tdc-1 // ------------------------------------------------------- // // 2) A root "makeclass" called Tracer.C (and Tracer.h) // is found in this source directory to help with examining // the pulse trace data collected from the fADC250 in raw // mode. See usage item above for an example session. // #define TRIGGERED_BY_PULSER 1 #include #include #include #include #include #include #include // root stuff #include #include #include #include #include #include #include #include #include #include "uconn.h" using namespace std; using namespace evio; int evtCount = 0; int verbose_print = 0; // prototypes void analyzeEvent(evioDOMTree &eventTree); void analyzeBank(evioDOMNodeP bankPtr); void initRootTree(const char* filename); bool event_passes_trigger(); // Define bit masks // F1 bit masks #define F1_RAW_DATA 0xFF000000 int main(int argc, char **argv) { if (argc == 1) { printf("Usage: uconn \n"); exit(1); } char filename[128]; strcpy(filename, argv[1]); try { char fname[128],fname1[128]; sprintf(fname,"%s",filename); strtok(fname,"_"); sprintf(fname1,"data/ntuple_%s.root",strtok(0,".")); initRootTree(fname1); cout << "open data file " << filename < 0) { fadc_pulse_raw[bd][ch]->Fill(float(samp),float(fadc_pulse[bd][ch][samp]),1.); } } } } #endif #if 0 for (unsigned int bd = 0; bd < 2; bd++) { for (unsigned int ch = 0; ch < 16; ch++) { for (unsigned int samp = 1; samp < window_size; samp++) { cout << fadc_pulse[bd][ch][samp] << endl; fadc_pulse[0][0][samp] = 17; } } } #endif if (event_passes_trigger()) { tree1->Fill(); } } chan.close(); ROOTfile->cd(); ROOTfile->Write(); ROOTfile->Close(); delete ROOTfile; cout<toString() << endl << endl; exit(EXIT_FAILURE); } cout << endl << endl << " ***File analyzer done after " << evtCount << " events***" << endl << endl; exit(EXIT_SUCCESS); } void analyzeEvent(evioDOMTree &eventTree) { evioDOMNodeListP bankList = eventTree.getNodeList(); for_each (bankList->begin(), bankList->end(), analyzeBank); } void analyzeBank(evioDOMNodeP bankPtr) { int SlotID = -1; int nboard = -1; int trigger_numb[max_fadc_board]; memset(trigger_numb,0,sizeof(trigger_numb)); switch (bankPtr->tag) { case 0: // ignore break; case 3: // header bank { const vector *vec = bankPtr->getVector(); if (vec == NULL) { cerr << "?unable to get header bank vector" << endl; return; } if (verbose_print) { cout << dec << "found header bank: run number " << (*vec)[0] << endl << " event number " << (*vec)[1] << endl << endl; } break; } case 6: // F1TDC data block { const vector *vec = bankPtr->getVector(); if (vec == NULL) { cerr << "?unable to get tdc bank vector" << endl; return; } if (verbose_print) { cout << " -------------------" << endl; cout << " F1TDC Vector Size = " << vec->size() << endl; cout << " -------------------" << endl; } for (unsigned i = 0; i < vec->size(); i++){ if (verbose_print) { cout << hex << (*vec)[i] << dec << endl; } if ((*vec)[i] == 0xf1daffff) continue; unsigned int data_type = ((*vec)[i] & 0x800000) >> 23; if (verbose_print) { cout << " Data type = " << data_type << endl; } if (data_type == 0) { // Event header unsigned int event_number = ((*vec)[i] & 0x3f0000) >> 16; unsigned int trigger_time = ((*vec)[i] & 0xff80) >> 7; unsigned int trigger_fifo_overflow = ((*vec)[i] & 0x400000) >> 22; unsigned int f1_chip = ((*vec)[i] & 0x38) >> 3; unsigned int f1_chan = ((*vec)[i] & 0x7); if (verbose_print) { cout << "Event Header: Event number = " << event_number << " Trigger time = " << trigger_time << " Chip = " << f1_chip << " Channel = " << f1_chan << " Trigger FIFO overflow = " << trigger_fifo_overflow << endl; } } else if (data_type == 1) { // Data if (verbose_print) { cout << endl; } unsigned int slot_id = ((*vec)[i] & 0xF8000000) >> 27; unsigned int chip_res_locked = ((*vec)[i] & 0x4000000) >> 26; unsigned int fifo_overflows = ((*vec)[i] & 0x3000000) >> 24; unsigned int f1_chip = ((*vec)[i] & 0x380000) >> 19; unsigned int f1_chan = ((*vec)[i] & 0x70000) >> 16; unsigned int f1_time = ((*vec)[i] & 0xffff); if (verbose_print) { cout << "Data word: Slot ID = " << slot_id << " Chip = " << f1_chip << " Channel = " << f1_chan << " Resolution Locked = " << chip_res_locked << " FIFO overflows = " << fifo_overflows << " cTime = " << f1_time << endl; } if (slot_id != F1TDC_SLOT) { cout << " F1TDC found in a wrong slot: " << slot_id << endl; continue; } if (chip_res_locked == 0) { cout << " FATAL: Chip Resolution is NOT locked " << "F1 CHIP = " << f1_chip << " Channel = " << f1_chan << endl; continue; } if (fifo_overflows != 0) { cout << " FATAL: FIFO overflows " << "F1 CHIP = " << f1_chip << " Channel = " << f1_chan << " FIFO overflow " << fifo_overflows << endl; continue; } if ( (f1_chip < 0) || (f1_chip > 7) ) { cout << "F1TDC: Wrong Chip Number " << f1_chip << endl; continue; } if ( (f1_chan == 0) || (f1_chan == 1) ) { if (nhit_tdc < max_tdc_hit) { tdc_ch[nhit_tdc] = f1_chip*4; tdc_time[nhit_tdc] = f1_time; nhit_tdc ++; } else { cout << " F1TDC: Too many hits " << " TDC Channel = " << tdc_ch << endl; } } if ((f1_chan == 2) || (f1_chan == 3)) { if (nhit_tdc < max_tdc_hit) { tdc_ch[nhit_tdc] = f1_chip*4 + 1; tdc_time[nhit_tdc] = f1_time; nhit_tdc ++; } else { cout << " F1TDC: Too many hits " << " TDC Channel = " << tdc_ch << endl; } } if ((f1_chan == 4) || (f1_chan == 5) ) { if (nhit_tdc < max_tdc_hit) { tdc_ch[nhit_tdc] = f1_chip*4 + 2; tdc_time[nhit_tdc] = f1_time; nhit_tdc ++; } else { cout << " F1TDC: Too many hits " << " TDC Channel = " << tdc_ch << endl; } } if ((f1_chan == 6) || (f1_chan == 7)) { if (nhit_tdc < max_tdc_hit) { tdc_ch[nhit_tdc] = f1_chip*4 + 3; tdc_time[nhit_tdc] = f1_time; nhit_tdc ++; } else { cout << " F1TDC: Too many hits " << " TDC Channel = " << tdc_ch << endl; } } } } break; } case 5: // FADC data block { const vector *vec = bankPtr->getVector(); if (vec == NULL) { cerr << "?unable to get fadc bank vector" << endl; return; } unsigned int data_new_type = 0; unsigned int data_type = 0; int channel = -1 ; unsigned int time_stamp = 0; unsigned int pulse_number = -1; unsigned int first_sample = -1; if (verbose_print) { cout << " Vector Size = " << vec->size() << endl; } float adc[2] = {0,0}; for (unsigned i = 0; i < vec->size(); i++) { // Bank header // bit 31 = 1 // bits 27- 30 = 0 // bits 22 - 26 = SlotID // bits 11 - 21 = Number of events in block; bits 0 - 10 event block number if ( (*vec)[i] >> 27 == 0x10 ) { /* Bank header 1000 0 */ SlotID = ((*vec)[i] & 0x7c00000) >> 22; nboard++; if (verbose_print) { cout << " FADC found in slot: " << SlotID << endl; } } // Event header // bit 31 = 1 // bits 27- 30 = 0x1001 // bits 0 - 26 = Trigger number else if ( (*vec)[i] >> 27 == 0x12 ) { /* Event header 1001 0 */ trigger_numb[nboard] = ((*vec)[i] & 0x7FFFFFF); if (verbose_print) { cout << " FADC found in slot: " << SlotID << " Trigger time " << trigger_numb[nboard] << endl; } } else if ( (*vec)[i] & 0x80000000 ) { /* data type defining word */ data_type = ((*vec)[i] & 0x78000000) >> 27; // data_type == 4 - window raw data // data_type == 6 - pulse raw data data_new_type = 1; } else { data_new_type = 0; }; if (data_type == 4 ) { // window raw data if (data_new_type == 1) { unsigned int fadc_width = ((*vec)[i] & 0xFFF); channel = ((*vec)[i] & 0x7800000) >> 23; if (verbose_print) { cout << " Data Type = " << data_type << " Fadc_width = " << fadc_width << " Channel = " << channel << endl; } time_stamp = 1; } else { unsigned int valid_1 = 1; unsigned int valid_2 = 1; unsigned int adc_1 = ((*vec)[i] & 0x1FFF0000) >> 16; if ((*vec)[i] & 0x20000000) { valid_1 = 0; } unsigned int adc_2 = ((*vec)[i] & 0x1FFF); if ( (*vec)[i] & 0x2000 ) { valid_2 = 0; } adc[0] = (adc_1 < 4000)? float(adc_1) : 0; adc[1] = (adc_2 < 4000)? float(adc_2) : 0; if (verbose_print) { cout << " Time stamp = " << time_stamp << " Nboard = " << nboard << " SlotID = " << SlotID << " Channel = " << channel << " ADC1 = " << adc[0] << " " << adc[1] << endl; } if ( (nboard >= 0) && (nboard < max_fadc_board) ) { if (fadc_slot[nboard] == SlotID) { if ((channel >= 0) && (channel < 16)) { fadc_raw[nboard][channel][time_stamp*2-2] = adc[0]; fadc_raw[nboard][channel][time_stamp*2-1] = adc[1]; fadc[nboard][channel]->Fill(float(time_stamp*2-2),adc[0],1.); fadc[nboard][channel]->Fill(float(time_stamp*2-1),adc[1],1.); ped[nboard][channel]->Fill(adc[0]); ped[nboard][channel]->Fill(adc[1]); } else { cout << " Wrong channel number " << channel << endl; exit(EXIT_FAILURE); } } else { cout << " Wrong FADC Slot. Exiting " << SlotID << endl; exit(EXIT_FAILURE); } } time_stamp++; } } else if (data_type == 6 ) { // raw pulse data if (data_new_type == 1) { channel = ((*vec)[i] & 0x7800000) >> 23; pulse_number = ((*vec)[i] & 0x600000) >> 21; first_sample = ((*vec)[i] & 0x3FF); if (verbose_print) { cout << endl; cout << " Data Type = " << data_type << " Channel = " << channel << " Pulse number = " << pulse_number << " First sample = " << first_sample << endl; cout << endl; } time_stamp = 1; } else { unsigned int valid_1 = -1; unsigned int valid_2 = -1; unsigned int adc_1 = ((*vec)[i] & 0x1FFF0000) >> 16; valid_1 = ((*vec)[i] & 0x20000000 ) >> 29; unsigned int adc_2 = ((*vec)[i] & 0x1FFF); valid_2 = ( (*vec)[i] & 0x2000 ) >> 13; float adc[2]; adc[0] = (adc_1 < 4000)? float(adc_1) : 0; adc[1] = (adc_2 < 4000)? float(adc_2) : 0; if ( (nboard >= 0) && (nboard < max_fadc_board) ) { if (fadc_slot[nboard] == SlotID) { if ((channel >= 0) && (channel < 16)) { int sample1 = time_stamp*2 - 2 + first_sample; int sample2 = time_stamp*2 - 1 + first_sample; if (sample2 > window_size) { if (verbose_print) { cout << " WRONG PULSE MODE ----- First Sample " << first_sample << " Time stamp " << time_stamp << endl; } } else if ( (sample2 < 1024) && (sample1 < 1024)) { fadc_pulse[nboard][channel][sample1] = adc[0]; fadc_pulse[nboard][channel][sample2] = adc[1]; } if (verbose_print) { cout << " Bd = " << nboard << " Ch = " << channel << " Words = " << time_stamp << " Sample 1 = " << sample1 << " Sample 2 = " << sample2 << " ADC 1 = " << adc[0] << " Valid1 " << valid_1 << " ADC 2 = " << adc[1] << " Valid2 " << valid_2 << endl; } } } else { cout << " Wrong channel number " << channel << endl; exit(EXIT_FAILURE); } } else { cout << " Wrong FADC Slot. Exiting " << SlotID << endl; exit(EXIT_FAILURE); } } time_stamp++; } if ( data_type == 7 ) { // Pulse Integral data channel = ((*vec)[i] & 0x7800000) >> 23; unsigned int pulse_numb = ((*vec)[i] & 0x200000) >> 21; unsigned int pulse_int = ((*vec)[i] & 0x3FFFF); if (verbose_print) { cout << " Channel = " << channel << " Pulse number = " << pulse_numb << " Pulse int = " << pulse_int << endl; } switch (channel) { case 0: pc0->Fill(float(pulse_int)); break; case 1: pc1->Fill(float(pulse_int)); break; case 2: pc2->Fill(float(pulse_int)); break; case 3: pc3->Fill(float(pulse_int)); break; case 4: pc4->Fill(float(pulse_int)); break; case 5: pc5->Fill(float(pulse_int)); break; case 6: pc6->Fill(float(pulse_int)); break; case 7: pc7->Fill(float(pulse_int)); break; case 8: pc8->Fill(float(pulse_int)); break; case 9: pc9->Fill(float(pulse_int)); break; case 10: pc10->Fill(float(pulse_int)); break; case 11: pc11->Fill(float(pulse_int)); break; case 12: pc12->Fill(float(pulse_int)); break; case 13: pc13->Fill(float(pulse_int)); break; case 14: pc14->Fill(float(pulse_int)); break; case 15: pc15->Fill(float(pulse_int)); break; default: break; } } } if (nboard >= 0) { for (Int_t nb = 0; nb < nboard; nb++) { if (trigger_numb[0] != trigger_numb[nb]) { cout << " FATAL: Trigger number mismatch " << trigger_numb[0] << " " << trigger_numb[nb] << endl; exit(EXIT_FAILURE); } if (verbose_print) { cout << " Trigger number " << trigger_numb[0] << " " << trigger_numb[1] << " " << trigger_numb[2] << endl; } } } break; } default: { break; } } } void initRootTree(const char* fname){ ROOTfile = new TFile(fname,"RECREATE","new"); cout << "Opened ROOT file " << fname << " ..." << endl; cout << "Create Root tree ..." << endl; ROOTfile->cd(); char tree_format_raw[50]; sprintf(tree_format_raw, "fadc_raw[2][16][%d]/I", window_size); char tree_format_pulse[50]; sprintf(tree_format_pulse, "fadc_pulse[2][16][%d]/I", window_size); tree1 = new TTree( "tree1", "Sipm test" ); tree1->Branch( "fadc_raw", &fadc_raw, tree_format_raw ); tree1->Branch( "fadc_pulse", &fadc_pulse, tree_format_pulse); tree1->Branch( "nhit_tdc", &nhit_tdc, "nhit_tdc/I" ); tree1->Branch( "tdc_ch", &tdc_ch, "tdc_ch[nhit_tdc]/I" ); tree1->Branch( "tdc_time", &tdc_time, "tdc_time[nhit_tdc]/I" ); // Profile histograms for fadcs operated in the raw window mode for (Int_t bd = 0; bd < max_fadc_board; bd++) { for (Int_t ch = 0; ch < 16; ch++) { char title[30]; sprintf(title, "fadc_%d_ch%d", bd, ch); fadc[bd][ch] = new TProfile(title,title,window_size,-0.5,window_size-0.5,-10.,4096); } } // 1D histograms for pedestals for (Int_t bd = 0; bd < max_fadc_board; bd++) { for (Int_t ch = 0; ch < 16; ch++) { char title[30]; sprintf(title,"ped_%d_ch%d",bd,ch); ped[bd][ch] = new TH1F(title,title,150,149.5,299.5); } } // Profile histograms for the raw pulse mode for (Int_t bd = 1; bd < max_fadc_board; bd++) { for (Int_t ch = 0; ch < 16; ch++) { char title[30]; sprintf(title,"fadc_pulse_raw%d_ch%d",bd,ch); fadc_pulse_raw[bd][ch] = new TProfile(title,title,window_size,-0.5,window_size-0.5,-10.,9000.); } } pc0 = new TH1F("pch 0","pch 0",3400,-0.5,3399.5); pc1 = new TH1F("pch 1","pch 1",3400,-0.5,3399.5); pc2 = new TH1F("pch 2","pch 2",3400,-0.5,3399.5); pc3 = new TH1F("pch 3","pch 3",3400,-0.5,3399.5); pc4 = new TH1F("pch 4","pch 4",3400,-0.5,3399.5); pc5 = new TH1F("pch 5","pch 5",3400,-0.5,3399.5); pc6 = new TH1F("pch 6","pch 6",3400,-0.5,3399.5); pc7 = new TH1F("pch 7","pch 7",3400,-0.5,3399.5); pc8 = new TH1F("pch 8","pch 8",3400,-0.5,3399.5); pc9 = new TH1F("pch 9","pch 9",3400,-0.5,3399.5); pc10 = new TH1F("pch 10","pch 10",3400,-0.5,3399.5); pc11 = new TH1F("pch 11","pch 11",3400,-0.5,3399.5); pc12 = new TH1F("pch 12","pch 12",3400,-0.5,3399.5); pc13 = new TH1F("pch 13","pch 13",3400,-0.5,3399.5); pc14 = new TH1F("pch 14","pch 14",40000,14999.5,54999.5); pc15 = new TH1F("pch 15","pch 15",300,-0.5,299.5); } bool event_passes_trigger() { int fadc = 0; pulse_analyzer pana(fadc_raw[fadc][0], 16, window_size); #if TRIGGERED_BY_PULSER double pheight_7 = pana.pheight_trig_pulser(7); double pheight_8 = pana.pheight_trig_pulser(8); #else double pheight_7 = pana.pheight_trig_summer(7); double pheight_8 = pana.pheight_trig_summer(8); #endif return true; return (pheight_7 > 110 && pheight_8 > 110); }