diff --git a/NoiseScan/ChangeName.C b/NoiseScan/ChangeName.C new file mode 100644 index 0000000..8d72703 --- /dev/null +++ b/NoiseScan/ChangeName.C @@ -0,0 +1,11 @@ +void ChangeName(std::string file_name="noise_1631202922451.root", float thresh=0){ + TFile* f = new TFile(file_name.c_str()); + auto pnoise = (o2::itsmft::NoiseMap*)f->Get("ccdb_object"); + int nbStrobes = pnoise->getNumOfStrobes(); + pnoise->applyProbThreshold(thresh, nbStrobes); + TFile * out = new TFile("noise.root", "recreate"); + out->cd(); + gDirectory->WriteObject(pnoise,"Noise"); + out->Close(); + +} diff --git a/NoiseScan/DiffNoise.C b/NoiseScan/DiffNoise.C new file mode 100644 index 0000000..7b505d7 --- /dev/null +++ b/NoiseScan/DiffNoise.C @@ -0,0 +1,251 @@ + + + +struct Chip { + int half, disk, face, zone, tr, row, col, noise; +}; + +bool compareInterval(Chip i1, Chip i2) +{ + if (i1.half < i2.half){ + return true; + }else if (i1.half == i2.half){ + if (i1.disk < i2.disk){ + return true; + }else if (i1.disk == i2.disk){ + if (i1.face < i2.face){ + return true; + }else if (i1.face == i2.face){ + if (i1.zone < i2.zone){ + return true; + }else if (i1.zone == i2.zone){ + if (i1.tr < i2.tr){ + return true; + }else{ + return false; + } + }else{ + return false; + } + }else{ + return false; + } + + }else{ + return false; + } + }else{ + return false; + } +} + +int AddressToColumn (int disk, int tr, int zone, int col, int row) +{ + int connector; + if (tr==5 || tr==6 || tr==7 || tr==24 || tr==23){ + connector = 0; + }else if (tr==0 || tr==1 || tr==2 || tr==3 || tr==4){ + connector = 1; + }else if (tr==17 || tr==16 || tr==15 || tr==14 || tr==13){ + connector = 2; + }else if (tr==22 || tr==21 || tr==20 || tr==19 || tr==18){ + connector = 3; + }else if (tr==12 || tr==11 || tr==10 || tr==9 || tr==8){ + connector = 4; + } + static constexpr Int_t ZoneRUType[4][5]{ + {1, 1, 1, 7, 11}, + {2, 2, 4, 8, 9}, + {2, 2, 3, 8, 10}, + {0, 0, 5, 6, 12}}; + std::array NChipsOnRUType{3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 4}; + int type; + int nb_connectors=0; + for (int z=0; z headers; + map filter; + auto calib = api.retrieveFromTFileAny("MFT/Calib/NoiseMap/", filter , timestamp_new, &headers ); + auto calibold = api.retrieveFromTFileAny("MFT/Calib/NoiseMap/", filter , timestamp_old, &headers ); + int nbStrobes = calib->getNumOfStrobes(); + int nbStrobesOld = calibold->getNumOfStrobes(); + calib->applyProbThreshold(thresh, nbStrobes); + calibold->applyProbThreshold(thresh, nbStrobesOld); + +// float thresh = 0; + vector DispPix; + vector vecNoise; + vector vecChip; + int nb_chips=0; + int tot_noise_count=0; + for (int id=0; id<936; id++){ + bool empty=true; + for (int row=0; row<512; row++){ + for (int col=0; col<1024; col++){ + int lvl = calib->getNoiseLevel(id, row, col); + int lvlold = calibold->getNoiseLevel(id, row, col); + + Int_t tr = chipMap[id].cable; + Int_t half = chipMap[id].half; + Int_t layer = chipMap[id].layer; + Int_t face = layer % 2; + Int_t disk = chipMap[id].disk; + Int_t zone = chipMap[id].zone; + + if (!lvl && lvlold ){ +// cout << "Noisy Pixel diseappeared : h" << half << "-d" << disk << "-f" << face << "-z" << zone << "-tr" << tr << ", row : " << row << " col : " << col << endl; + DispPix.push_back({half, disk, face, zone, tr, row, col, lvlold}); + + } + if (lvl && !lvlold){ +// cout << "New Noisy Pixel : h" << half << "-d" << disk << "-f" << face << "-z" << zone << "-tr" << tr << ", row : " << row << " col : " << col << endl; + vecChip.push_back({half, disk, face, zone, tr, row, col, lvl}); + empty=false; + } + if (lvl) + tot_noise_count++; + + } + } + if (!empty){ + nb_chips++; + } + } +// sort(vecChip.begin(), vecChip.end(), compareInterval); + int nb_pixels = vecChip.size(); + cout << nb_pixels << endl; + + delete calib; + delete calibold; + + TCanvas *c1[20]; + TH2F *hplot[20]; + int count[20]; + int count_disp[20]; + int countz[20][4]; + int countz_disp[20][4]; + for(int i=0;i<20;i++){ + for (int f=0; f<4; f++){ + countz[i][f]=0; + countz_disp[i][f]=0; + } + count[i]=0; + count_disp[i]=0; + string histoname; + int f = i%2; + if (i < 10){ + histoname = "h0-d"+to_string((i-f)/2)+"-f"+to_string(f); + }else{ + histoname = "h1-d"+to_string((i-f)/2-5)+"-f"+to_string(f); + } + hplot[i] = new TH2F(histoname.c_str(),histoname.c_str(),17*512,-0.5,17*512-0.5,5*1024,-0.5,5*1024-0.5); + } + + + for (int i=0; iFill(Column, Row, vecChip[i].noise); + count[index]++; + countz[index][vecChip[i].zone]++; + + } + + int nb_disp = DispPix.size(); + for (int i=0; icd(k); + gStyle->SetOptStat(0); + hplot[k]->Draw("colz"); + int f = k%2; + if (k < 10){ + cout << "h0-d" << (k-f)/2 << "-f" << f << " : " << count[k] << endl; + }else{ + cout << "h1-d"<< (k-f)/2-5 << "-f" << f << " : " << count[k] << endl;; + } + } + cout << '\n' << '\t' << "Detail : " << endl; + for(int k=0;k<20;k++){ //to have the plot + int face = k%2; + for(int f=0; f<4; f++){ + if (k < 10){ + cout << '\t' << "h0-d" << (k-face)/2 << "-f" << face << "-z" << f << " : " << countz[k][f] << endl; + }else{ + cout << '\t' << "h1-d"<< (k-face)/2-5 << "-f" << face << "-z" << f <<" : " << countz[k][f] << endl;; + } + } + } + cout << '\n' << "Noisy pixels that disapeared : " << endl; + for(int k=0;k<20;k++){ //to have the plot + int f = k%2; + if (k < 10){ + cout << "h0-d" << (k-f)/2 << "-f" << f << " : " << count_disp[k] << endl; + }else{ + cout << "h1-d"<< (k-f)/2-5 << "-f" << f << " : " << count_disp[k] << endl;; + } + } + cout << '\n' << '\t' << "Detail : " << endl; + for(int k=0;k<20;k++){ //to have the plot + int face = k%2; + for(int f=0; f<4; f++){ + if (k < 10){ + cout << '\t' << "h0-d" << (k-face)/2 << "-f" << face << "-z" << f <<" : " << countz_disp[k][f] << endl; + }else{ + cout << '\t' << "h1-d"<< (k-face)/2-5 << "-f" << face << "-z" << f <<" : " << countz_disp[k][f] << endl;; + } + } + } + cout << '\n' << "Noisy pixels that disapeared : " << endl; + cout << "Total new noisy pixels : " << nb_pixels << endl; + cout << "Total noisy pixels that disappeared : " << nb_disp << endl; + cout << "Current total nb of noisy pixels : " << tot_noise_count << endl; + + + +} diff --git a/NoiseScan/NoisePlotDisk.C b/NoiseScan/NoisePlotDisk.C new file mode 100644 index 0000000..1cc0b5f --- /dev/null +++ b/NoiseScan/NoisePlotDisk.C @@ -0,0 +1,184 @@ + + + +struct Chip { + int half, disk, face, zone, tr, row, col, noise; +}; + +bool compareInterval(Chip i1, Chip i2) +{ + if (i1.half < i2.half){ + return true; + }else if (i1.half == i2.half){ + if (i1.disk < i2.disk){ + return true; + }else if (i1.disk == i2.disk){ + if (i1.face < i2.face){ + return true; + }else if (i1.face == i2.face){ + if (i1.zone < i2.zone){ + return true; + }else if (i1.zone == i2.zone){ + if (i1.tr < i2.tr){ + return true; + }else{ + return false; + } + }else{ + return false; + } + }else{ + return false; + } + + }else{ + return false; + } + }else{ + return false; + } +} + +int AddressToColumn (int disk, int tr, int zone, int col, int row) +{ + int connector; + if (tr==5 || tr==6 || tr==7 || tr==24 || tr==23){ + connector = 0; + }else if (tr==0 || tr==1 || tr==2 || tr==3 || tr==4){ + connector = 1; + }else if (tr==17 || tr==16 || tr==15 || tr==14 || tr==13){ + connector = 2; + }else if (tr==22 || tr==21 || tr==20 || tr==19 || tr==18){ + connector = 3; + }else if (tr==12 || tr==11 || tr==10 || tr==9 || tr==8){ + connector = 4; + } + static constexpr Int_t ZoneRUType[4][5]{ + {1, 1, 1, 7, 11}, + {2, 2, 4, 8, 9}, + {2, 2, 3, 8, 10}, + {0, 0, 5, 6, 12}}; + std::array NChipsOnRUType{3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 4}; + int type; + int nb_connectors=0; + for (int z=0; z headers; + map filter; + auto calib = api.retrieveFromTFileAny("MFT/Calib/NoiseMap/", filter , timestamp, &headers ); + int nbStrobes = calib->getNumOfStrobes(); + calib->applyProbThreshold(thresh, nbStrobes); + + vector vecNoise; + vector vecChip; + int nb_chips=0; + for (int id=0; id<936; id++){ + bool empty=true; + for (int row=0; row<512; row++){ + for (int col=0; col<1024; col++){ + int lvl = calib->getNoiseLevel(id, row, col); + if (lvl > thresh*calib->getNumOfStrobes()){ + Int_t tr = chipMap[id].cable; + Int_t half = chipMap[id].half; + Int_t layer = chipMap[id].layer; + Int_t face = layer % 2; + Int_t disk = chipMap[id].disk; + Int_t zone = chipMap[id].zone; + + vecChip.push_back({half, disk, face, zone, tr, row, col, lvl}); + + empty=false; + } + } + } + if (!empty){ + nb_chips++; + } + } +// sort(vecChip.begin(), vecChip.end(), compareInterval); + int nb_pixels = vecChip.size(); + cout << nb_pixels << endl; + + TCanvas *c1[20]; + TH2F *hplot[20]; + int countz[20][4]; + for(int i=0;i<20;i++){ + for (int f=0; f<4; f++){ + countz[i][f]=0; + } + string histoname; + int f = i%2; + if (i < 10){ + histoname = "h0-d"+to_string((i-f)/2)+"-f"+to_string(f); + }else{ + histoname = "h1-d"+to_string((i-f)/2-5)+"-f"+to_string(f); + } + hplot[i] = new TH2F(histoname.c_str(),histoname.c_str(),17*512,-0.5,17*512-0.5,5*1024,-0.5,5*1024-0.5); + } + + + for (int i=0; iFill(Column, Row, vecChip[i].noise); + countz[index][vecChip[i].zone]++; + + } + cout << '\n' << "Noisy pixels per zone : " << endl; + for(int k=0;k<20;k++){ //to have the plot + int face = k%2; + for(int f=0; f<4; f++){ + if (k < 10){ + cout << '\t' << "h0-d" << (k-face)/2 << "-f" << face << "-z" << f << " : " << countz[k][f] << endl; + }else{ + cout << '\t' << "h1-d"<< (k-face)/2-5 << "-f" << face << "-z" << f <<" : " << countz[k][f] << endl;; + } + } + } + + for(int k=0;k<20;k++){ //to have the plot + c1[k]= new TCanvas(); + c1[k]->cd(k); + gStyle->SetOptStat(0); + hplot[k]->Draw("colz"); + } + + + +} diff --git a/NoiseScan/README.md b/NoiseScan/README.md new file mode 100644 index 0000000..0d10e1b --- /dev/null +++ b/NoiseScan/README.md @@ -0,0 +1,14 @@ +# Tools for noise calibration + +### `root readCCDB.C` +displays the list of noisy pixels in the last NoiseMap object written in the CCDB. It can also displays any CCDB entry provided the correct timestamp with a command such as : `root -b -q "readCCDB.C(1625066988580)"` (a timestamp=-1 means the latest entry in the CCDB). + +### `root -b -q -l 'ChangeName.C("noise_1625066988580.root")'` +takes as input the name of a root file downloaded locally from the CCDB containing a NoiseMap object and writes in output a file noise.root which contains the same NoiseMap but withe the correct name ("Noise") to be used by the decoder to mask noisy pixels. + +### `root -b -q -l "DiffNoise.C(-1,1625066988580)"` +takes as input the timestamps of two NoiseMap objects in the CCDB to be comapred. The macro will output the list per zone of noisy pixels that are new and the noisy pixels that diseappeared. + +### `root -b NoisePlotDisk.C` +plots the content of the latest NoiseMap object in the CCDB in the usual half-disk 2D histograms. + diff --git a/NoiseScan/example_command.sh b/NoiseScan/example_command.sh new file mode 100644 index 0000000..d3ae817 --- /dev/null +++ b/NoiseScan/example_command.sh @@ -0,0 +1,5 @@ +#!/bin/bash +root -b -q readCCDB.C +root -b -q -l 'ChangeName.C("test.root")' +root -b "DiffNoise.C(-1,1625066988580)" + diff --git a/NoiseScan/plotCCDB.C b/NoiseScan/plotCCDB.C new file mode 100644 index 0000000..d1781c4 --- /dev/null +++ b/NoiseScan/plotCCDB.C @@ -0,0 +1,136 @@ +void plotCCDB(){ + o2::ccdb::CcdbApi api; + api.init("http://alice-ccdb.cern.ch"); + map headers; + map filter; + auto calib = api.retrieveFromTFileAny("MFT/Calib/NoiseMap/", filter , -1, &headers ); + float thresh = 0; +// calib->dumpAboveThreshold(thresh); + vector vecNoise; + int nb_chips=0; + for (int id=0; id<936; id++){ + bool empty=true; + for (int row=0; row<512; row++){ + for (int col=0; col<1024; col++){ + int lvl = calib->getNoiseLevel(id, row, col); +// if (lvl && id > 467){ + if (lvl && id < 468){ +// cout << "Noise level (id, row col, noise) : " << id << ", " << row << ", " << col << ", " << lvl << endl; + vecNoise.push_back(lvl); + empty=false; + } + } + } + if (!empty){ + nb_chips++; + } + } + cout << "Number of strobes : " << calib->getNumOfStrobes() << endl; + int ROFs = calib->getNumOfStrobes(); + int nb_pixels = vecNoise.size(); +// int sizeVecDec = 936; +// int sizeVecDec = 468; + int sizeVecDec = nb_chips; + cout << "Number of noisy pixels : " << nb_pixels << endl; + double occupancy[nb_pixels]; + double masked_pixels[nb_pixels]; + sort(vecNoise.begin(), vecNoise.end()); + int total = 0; + int index_99=0; + int index_10=0; + int index_01=0; + int index_101=0; + int index_3=0; + int index_2=0; + cout << "Tot nb pixels : " << nb_pixels << endl; + for(int i=0; i2 && vecNoise[i] < 101){ + index_101=nb_pixels-i-1; + }else if (vecNoise[i]>100 && vecNoise[i] < 0.001*ROFs){ + index_01=nb_pixels-i-1; + }else if (vecNoise[i]>0.001*ROFs && vecNoise[i] < 0.1*ROFs){ + index_10=nb_pixels-i-1; + }else if (vecNoise[i]>0.1*ROFs && vecNoise[i] < 0.99*ROFs){ + index_99=nb_pixels-i-1; + } + double tot_pixels = ROFs*1024.*512.*((double) sizeVecDec); + occupancy[nb_pixels-i-1]= (double) total / (double) tot_pixels; + cout << "Occupancy : " << occupancy[nb_pixels-i-1] << endl; + masked_pixels[i]=i; + } + cout << "index 2 : " << index_2 << ", 3 : " << index_3 << ", 101 : " << index_101 << ", 01 : " << index_01 << ", 10 : " << index_10 << ", 99 : " << index_99 << endl; +// cout << "Nb pixels w/ 1 hit: " << nb_pixels-index_2 << endl; +// cout << "Nb pixels w/ 2 hit: " << index_2-index_3 << endl; +// cout << "Nb pixels w/ 3-100 hit: " << index_3-index_101 << endl; + cout << "Nb pixels w/ 101-0.1\% hit: " << nb_pixels-index_01 << endl; + cout << "Nb pixels w/ 0.1\%-10\% hit: " << index_01-index_10 << endl; + cout << "Nb pixels w/ 10\%-99\% hit: " << index_10-index_99 << endl; + cout << "Nb pixels w/ >99\% hit: " << index_99 << endl; + TGraph *grshade_1 = new TGraph(2*index_99); + grshade_1->SetName("grshade_1"); + for (int i=0;iSetPoint(i,masked_pixels[i],occupancy[i]); + grshade_1->SetPoint(index_99+i,masked_pixels[index_99-i-1],0); + } + grshade_1->SetFillStyle(3001); + grshade_1->SetFillColor(41); + TGraph *grshade_01 = new TGraph(2*(nb_pixels-index_01)); + grshade_01->SetName("grshade_01"); + for (int i=0;i<(nb_pixels-index_01);i++) { + grshade_01->SetPoint(i,masked_pixels[i+index_01],occupancy[i+index_01]); + grshade_01->SetPoint((nb_pixels-index_01)+i,masked_pixels[nb_pixels-i-1],0); + } + grshade_01->SetFillStyle(3001); + grshade_01->SetFillColor(5); + TGraph *grshade_10 = new TGraph(2*(index_01-index_10)); + grshade_10->SetName("grshade_10"); + for (int i=0;i<(index_01-index_10);i++) { + grshade_10->SetPoint(i,masked_pixels[i+index_10],occupancy[i+index_10]); + grshade_10->SetPoint((index_01-index_10)+i,masked_pixels[index_01-i-1],0); + } + grshade_10->SetFillStyle(3001); + grshade_10->SetFillColor(6); + TGraph *grshade_99 = new TGraph(2*(index_10-index_99)); + grshade_99->SetName("grshade_99"); + for (int i=0;i<(index_10-index_99);i++) { + grshade_99->SetPoint(i,masked_pixels[i+index_99],occupancy[i+index_99]); + grshade_99->SetPoint((index_10-index_99)+i,masked_pixels[index_10-i-1],0); + } + grshade_99->SetFillStyle(3001); + grshade_99->SetFillColor(7); + + TGraph *gr = new TGraph(nb_pixels,masked_pixels,occupancy); + gr->SetTitle("; # masked pixels; Noise occupancy per pixel per event"); + gr->SetName("gr"); + gr->SetMarkerColor(2); + gr->SetLineColor(2); + gr->SetLineWidth(3); + gr->SetMarkerSize(0.5); + gr->SetMarkerStyle(7); + + auto c = new TCanvas("c", "c", 750, 500); + + gr->Draw("AC*"); + gr->GetYaxis()->SetRangeUser(1e-13,5e-6); + gr->GetXaxis()->SetRangeUser(1,1e5); + grshade_1->Draw("f"); + grshade_01->Draw("f"); + grshade_10->Draw("f"); + grshade_99->Draw("f"); + + auto legend = new TLegend(0.6, 0.7, 0.9, 0.9); + legend->AddEntry("grshade_01", Form("(101 - 0.1 \%) : %d pixels",nb_pixels-index_01), "f"); + legend->AddEntry("grshade_10", Form("(0.1 \% - 10 \%) : %d pixels",index_01-index_10), "f"); + legend->AddEntry("grshade_99", Form("(10 \% - 99 \%) : %d pixels",index_10-index_99), "f"); + legend->AddEntry("grshade_1", Form("(>99 \%) : %d pixels",index_99), "f"); + legend->Draw(); + + + + +} diff --git a/NoiseScan/readCCDB.C b/NoiseScan/readCCDB.C new file mode 100644 index 0000000..b61384f --- /dev/null +++ b/NoiseScan/readCCDB.C @@ -0,0 +1,11 @@ +void readCCDB(long timestamp=-1, float thresh=0){ + o2::ccdb::CcdbApi api; + api.init("http://alice-ccdb.cern.ch"); + map headers; + map filter; + auto calib = api.retrieveFromTFileAny("MFT/Calib/NoiseMap/", filter , timestamp, &headers); + calib->dumpAboveProbThreshold(thresh); + cout << "Number of strobes : " << calib->getNumOfStrobes() << endl; + + +} diff --git a/NoiseScan/sortNoiseMap.C b/NoiseScan/sortNoiseMap.C new file mode 100644 index 0000000..5f2a49f --- /dev/null +++ b/NoiseScan/sortNoiseMap.C @@ -0,0 +1,93 @@ + + + +struct Chip { + int half, disk, face, zone, tr, row, col, noise; +}; + +bool compareInterval(Chip i1, Chip i2) +{ + if (i1.half < i2.half){ + return true; + }else if (i1.half == i2.half){ + if (i1.disk < i2.disk){ + return true; + }else if (i1.disk == i2.disk){ + if (i1.face < i2.face){ + return true; + }else if (i1.face == i2.face){ + if (i1.zone < i2.zone){ + return true; + }else if (i1.zone == i2.zone){ + if (i1.tr < i2.tr){ + return true; + }else{ + return false; + } + }else{ + return false; + } + }else{ + return false; + } + + }else{ + return false; + } + }else{ + return false; + } +} + +void sortNoiseMap(long timestamp=-1){ + + const o2::itsmft::ChipMappingMFT maping; + auto chipMap = maping.getChipMappingData(); + + o2::ccdb::CcdbApi api; + api.init("ccdb-test.cern.ch:8080"); + map headers; + map filter; + auto calib = api.retrieveFromTFileAny("MFT/Calib/NoiseMap/", filter , timestamp, &headers ); + float thresh = 0; +// calib->dumpAboveThreshold(thresh); + vector vecNoise; + vector vecChip; + int nb_chips=0; + for (int id=0; id<936; id++){ + bool empty=true; + for (int row=0; row<512; row++){ + for (int col=0; col<1024; col++){ + int lvl = calib->getNoiseLevel(id, row, col); + if (lvl){ + Int_t cableHW = chipMap[id].cable; + Int_t half = chipMap[id].half; + Int_t layer = chipMap[id].layer; + Int_t face = layer % 2; + Int_t disk = chipMap[id].disk; + Int_t zone = chipMap[id].zone; + + vecChip.push_back({half, disk, face, zone, cableHW, row, col, lvl}); + + empty=false; + } + } + } + if (!empty){ + nb_chips++; + } + } + sort(vecChip.begin(), vecChip.end(), compareInterval); + int nb_pixels = vecChip.size(); + cout << nb_pixels << endl; + + std::ofstream OutStream; + OutStream.open("noiseMap_sorted.csv"); + OutStream << "half,disk,face,zone,tr,row,col,nhits"<< endl; + + for (int i=0; i ~/alice/decoding-scripts/decode-mc-hit-pattern.sh +ls -1 2021-05-03*.tf | awk '{print "./run_decoding_workflow.sh 0.001 0 /home/mft/data/mw4/151 256 " $1}' > ~/alice/decoding-scripts/decode-mc-hit-pattern.sh +#ls -1 2021-04-01*.tf | awk '{print "./run_decoding_workflow.sh 0.001 0 /home/mft/data/mw3/63 256 " $1}' > ~/alice/decoding-scripts/decode-mc-hit-pattern.sh #ls -1 data-2021_03_12__16_24_08__-20* | awk '{print "./run_decoding_workflow.sh 0.001 /home/mft/data 128 " $1}' > ~/alice/decoding-scripts/decode-noise-scan.sh #ls -1 data-2021_03_12__18_28_10__-20* | awk '{print "./run_decoding_workflow.sh 0.01 /home/mft/data 128 " $1}' > ~/alice/decoding-scripts/decode-source-long-scan-nobb.sh #ls -1 data-2021_03_12__19_29_35__-20* | awk '{print "./run_decoding_workflow.sh 0.01 /home/mft/data 128 " $1}' > ~/alice/decoding-scripts/decode-source-long-scan-wbb.sh diff --git a/custom_env_epn157.sh b/custom_env_epn157.sh new file mode 100755 index 0000000..9978544 --- /dev/null +++ b/custom_env_epn157.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash + +function go_o2() { + # enter O2 environment + module load O2PDPSuite +} +export -f go_o2 + +function go_eos() { + # needed to be able to acces EOS files + export XrdSecPROTOCOL=sss,unix + export XrdSecSSSKT=~/.alimftvs.sss.keys +} +export -f go_eos + +function groupfiles () { + # create a subgroup of files for reco + # from a list of files, obtained for e.g. with: + # xrdfs root://eosaliceo2.cern.ch ls /eos/aliceo2/ls2data/GC/ECS/compressed/2TkZ5uNgEvW_502879 > ctflist + # use: + # FilesPerGroup=15 groupfiles ctflist + # alternatively, use the bash program split instead: + # split -l 15 -d ctflist group_ + FilesPerGroup=${FilesPerGroup:-"50"} + GroupCounter=0 + FileCounter=0 + rm group_* + for file in $(cat $@) + do + echo ${file} >> group_${GroupCounter} + ((FileCounter++)) + + if [ ${FileCounter} -eq ${FilesPerGroup} ] + then + ((GroupCounter++)) + FileCounter=0 + fi + done +} +export -f groupfiles + +function go_tf_reco() { + # read TF file(s), run reco workflow on these files, output tracks and cluster ROOT files + # with a list of TF files obtained from for e.g. + # xrdfs root://eosaliceo2.cern.ch ls /eos/aliceo2/ls2data/GC/ECS/raw/2021-10-01_18-29/run0502879_2021-10-01T18_30_45Z > tflist + # use: + # go_tfreco tflist + inputfile=${@} + prefix=${@} + +# o2-raw-tf-reader-workflow --shm-segment-size 15000000000 --input-data ${inputfile} --onlyDet MFT | o2-itsmft-stf-decoder-workflow --shm-segment-size 15000000000 --nthreads 8 --runmft --digits --no-clusters --no-cluster-patterns | o2-mft-reco-workflow --mft-track-writer "--outfile mfttracks_${prefix}.root" --mft-cluster-writer "--outfile mftclusters_${prefix}.root" --shm-segment-size 15000000000 --digits-from-upstream --disable-mc --configKeyValues "MFTTracking.FullClusterScan=true; MFTTracking.MinTrackPointsLTF=3; MFTTracking.MinTrackStationsLTF=1; MFTTracking.LTFclsRCut=0.5; MFTTracking.LTFseed2BinWin=6; MFTTracking.MinTrackStationsCA=1; MFTTracking.ROADclsRCut=0.5; MFTTracking.MinTrackPointsCA=3;" --run | tee decode_and_reco_TF${prefix}.log + o2-raw-tf-reader-workflow --shm-segment-size 15000000000 --input-data ${inputfile} --onlyDet MFT | o2-itsmft-stf-decoder-workflow --shm-segment-size 15000000000 --nthreads 8 --runmft --digits --no-clusters --no-cluster-patterns | o2-mft-reco-workflow --mft-track-writer "--outfile mfttracks_${prefix}.root" --mft-cluster-writer "--outfile mftclusters_${prefix}.root" --shm-segment-size 15000000000 --digits-from-upstream --disable-mc --configKeyValues "MFTTracking.FullClusterScan=true; MFTTracking.MinTrackPointsLTF=3; MFTTracking.MinTrackStationsLTF=1; MFTTracking.LTFclsRCut=0.5; MFTTracking.LTFseed2BinWin=6; MFTTracking.MinTrackStationsCA=1; MFTTracking.ROADclsRCut=0.5; MFTTracking.MinTrackPointsCA=3;" -b --run > decode_and_reco_TF${prefix}.log && mv ${inputfile} done_${inputfile} +} +export -f go_tf_reco + +function go_tf_to_digits() { + # read TF file(s), run decoder on these files, output digit ROOT files + # with a list of TF files obtained from for e.g. + # xrdfs root://eosaliceo2.cern.ch ls /eos/aliceo2/ls2data/GC/ECS/raw/2021-10-01_18-29/run0502879_2021-10-01T18_30_45Z > tflist + # use: + # go_tf_to_digits tflist + inputfile=${@} + prefix=${@} + + o2-raw-tf-reader-workflow --shm-segment-size 15000000000 --input-data ${inputfile} --onlyDet MFT | o2-itsmft-stf-decoder-workflow --shm-segment-size 15000000000 --nthreads 8 --runmft --digits --no-clusters --no-cluster-patterns | o2-itsmft-digit-writer-workflow --disable-mc --outfile mftdigits_${prefix}.root -b --runmft > decode_and_digits_TF${prefix}.log && mv ${inputfile} done_${inputfile} +} +export -f go_tf_to_digits + +function go_ctf_reco() { + # read CTF file(s), run reco workflow on these files, output tracks and cluster ROOT files + # with a list of CTF files obtained from for e.g. + # xrdfs root://eosaliceo2.cern.ch ls /eos/aliceo2/ls2data/GC/ECS/compressed/2TkZ5uNgEvW_502879 > ctflist + # use: + # go_ctf_reco ctflist + inputfile=${@} + MINCLUSTERS=${MINCLUSTERS:-"4"} + ROADRADIUS=${ROADRADIUS:-"0.1"} + prefix=${@}_${MINCLUSTERS}cls_${ROADRADIUS}road + + o2-ctf-reader-workflow --onlyDet MFT --delay 0.1 --ctf-input ${inputfile} | o2-mft-reco-workflow --mft-track-writer "--outfile mfttracks_${prefix}.root" --mft-cluster-writer "--outfile mftclusters_${prefix}.root" --shm-segment-size 15000000000 --clusters-from-upstream --disable-mc --configKeyValues "MFTTracking.FullClusterScan=true; MFTTracking.MinTrackPointsLTF=${MINCLUSTERS}; MFTTracking.MinTrackStationsLTF=1; MFTTracking.LTFclsRCut=${ROADRADIUS}; MFTTracking.LTFseed2BinWin=6; MFTTracking.MinTrackStationsCA=1; MFTTracking.ROADclsRCut=${ROADRADIUS}; MFTTracking.MinTrackPointsCA=${MINCLUSTERS};" -b --run > reco_${prefix}.log && mv ${inputfile} done_${inputfile} +} + +export -f go_ctf_reco + +function go_cluster_reco() { + # read cluster file(s), run reco workflow on these clusters, output tracks and cluster ROOT files + # use: + # go_cluster_reco file_with_clusterfilelist + inputfile=${@} + MINCLUSTERS=${MINCLUSTERS:-"4"} + ROADRADIUS=${ROADRADIUS:-"0.5"} + prefix=${@}_${MINCLUSTERS}cls_${ROADRADIUS}road + + o2-mft-cluster-reader-workflow --shm-segment-size 15000000000 --mft-cluster-infile ${inputfile} | o2-mft-reco-workflow --mft-track-writer "--outfile mfttracks_${prefix}.root" --mft-cluster-writer "--outfile /dev/null" --shm-segment-size 15000000000 --clusters-from-upstream --disable-mc --configKeyValues "MFTTracking.FullClusterScan=true; MFTTracking.MinTrackPointsLTF=${MINCLUSTERS}; MFTTracking.MinTrackStationsLTF=1; MFTTracking.LTFclsRCut=${ROADRADIUS}; MFTTracking.LTFseed2BinWin=10; MFTTracking.MinTrackStationsCA=1; MFTTracking.ROADclsRCut=${ROADRADIUS}; MFTTracking.MinTrackPointsCA=${MINCLUSTERS};" -b --run > reco_${prefix}.log +} +export -f go_cluster_reco + diff --git a/custom_env_lxplus.sh b/custom_env_lxplus.sh new file mode 100755 index 0000000..bebc7c5 --- /dev/null +++ b/custom_env_lxplus.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash + +# make sure that you are using O2 from CVMFS +# via for e.g. +# > /cvmfs/alice.cern.ch/bin/alienv enter VO_ALICE@O2PDPSuite::nightly-20211026-1 +# or +# > /cvmfs/alice.cern.ch/bin/alienv enter VO_ALICE@O2Physics::nightly-20211026-1 + +function groupfiles () { + # create a subgroup of files for reco + # from a list of files, obtained for e.g. with: + # alien_ls -c /alice/data/2021/OCT/504980/raw/*.tf > tflist + # or + # alien_ls -c /alice/data/2021/OCT/504980/raw/*.root > ctflist + # use: + # FilesPerGroup=15 groupfiles ctflist + # alternatively, use the bash program split instead: + # split -l 15 -d ctflist group_ + FilesPerGroup=${FilesPerGroup:-"50"} + GroupCounter=0 + FileCounter=0 + rm group_* + for file in $(cat $@) + do + echo ${file} >> group_${GroupCounter} + ((FileCounter++)) + + if [ ${FileCounter} -eq ${FilesPerGroup} ] + then + ((GroupCounter++)) + FileCounter=0 + fi + done +} +export -f groupfiles + +function go_tf_to_digits() { + # read TF file(s), run decoder on these files, output digit ROOT files + # with a list of TF files obtained from for e.g. + # alien_ls -c /alice/data/2021/OCT/504980/raw/*.tf > tflist + # use: + # go_tf_to_digits tflist + inputfile=${@} + prefix=${@} + + o2-raw-tf-reader-workflow --copy-cmd "alien_cp ?src ?dst" --remote-regex "/alice/data/2021/.+" --shm-segment-size 15000000000 --input-data ${inputfile} --onlyDet MFT | o2-itsmft-stf-decoder-workflow --shm-segment-size 15000000000 --nthreads 8 --runmft --digits --no-clusters --no-cluster-patterns | o2-itsmft-digit-writer-workflow --disable-mc --outfile mftdigits_${prefix}.root -b --runmft > decode_and_digits_TF${prefix}.log && mv ${inputfile} done_${inputfile} +} +export -f go_tf_to_digits + + +function go_tf_reco() { + # read TF file(s), run reco workflow on these files, output tracks and cluster ROOT files + # with a list of TF files obtained from for e.g. + # alien_ls -c /alice/data/2021/OCT/504980/raw/*.tf > tflist + # use: + # go_tfreco tflist + inputfile=${@} + prefix=${@} + + o2-raw-tf-reader-workflow --copy-cmd "alien_cp ?src ?dst" --remote-regex "/alice/data/2021/.+" --shm-segment-size 15000000000 --input-data ${inputfile} --onlyDet MFT | o2-itsmft-stf-decoder-workflow --shm-segment-size 15000000000 --nthreads 8 --runmft --digits --no-clusters --no-cluster-patterns | o2-mft-reco-workflow --mft-track-writer "--outfile mfttracks_${prefix}.root" --mft-cluster-writer "--outfile mftclusters_${prefix}.root" --shm-segment-size 15000000000 --digits-from-upstream --disable-mc --configKeyValues "MFTTracking.FullClusterScan=true; MFTTracking.MinTrackPointsLTF=3; MFTTracking.MinTrackStationsLTF=1; MFTTracking.LTFclsRCut=0.5; MFTTracking.LTFseed2BinWin=6; MFTTracking.MinTrackStationsCA=1; MFTTracking.ROADclsRCut=0.5; MFTTracking.MinTrackPointsCA=3;" -b --run > decode_and_reco_TF${prefix}.log && mv ${inputfile} done_${inputfile} +} +export -f go_tf_reco + +function go_ctf_reco() { + # read CTF file(s), run reco workflow on these files, output tracks and cluster ROOT files + # with a list of CTF files obtained from for e.g. + # alien_ls -c /alice/data/2021/OCT/504980/raw/*.root > ctflist + # use: + # go_ctf_reco ctflist + inputfile=${@} + MINCLUSTERS=${MINCLUSTERS:-"4"} + ROADRADIUS=${ROADRADIUS:-"0.1"} + prefix=${@}_${MINCLUSTERS}cls_${ROADRADIUS}road + + o2-ctf-reader-workflow --copy-cmd "alien_cp ?src ?dst" --remote-regex "/alice/data/2021/.+" --onlyDet MFT --delay 0.1 --ctf-input ${inputfile} | o2-mft-reco-workflow --mft-track-writer "--outfile mfttracks_${prefix}.root" --mft-cluster-writer "--outfile mftclusters_${prefix}.root" --shm-segment-size 15000000000 --clusters-from-upstream --disable-mc --configKeyValues "MFTTracking.FullClusterScan=true; MFTTracking.MinTrackPointsLTF=${MINCLUSTERS}; MFTTracking.MinTrackStationsLTF=1; MFTTracking.LTFclsRCut=${ROADRADIUS}; MFTTracking.LTFseed2BinWin=6; MFTTracking.MinTrackStationsCA=1; MFTTracking.ROADclsRCut=${ROADRADIUS}; MFTTracking.MinTrackPointsCA=${MINCLUSTERS};" -b --run > reco_${prefix}.log && mv ${inputfile} done_${inputfile} +} + +export -f go_ctf_reco + +function go_cluster_reco() { + # read cluster file(s), run reco workflow on these clusters, output tracks and cluster ROOT files + # use: + # go_cluster_reco file_with_clusterfilelist + inputfile=${@} + MINCLUSTERS=${MINCLUSTERS:-"4"} + ROADRADIUS=${ROADRADIUS:-"0.5"} + prefix=${@}_${MINCLUSTERS}cls_${ROADRADIUS}road + + o2-mft-cluster-reader-workflow --shm-segment-size 15000000000 --mft-cluster-infile ${inputfile} | o2-mft-reco-workflow --mft-track-writer "--outfile mfttracks_${prefix}.root" --mft-cluster-writer "--outfile /dev/null" --shm-segment-size 15000000000 --clusters-from-upstream --disable-mc --configKeyValues "MFTTracking.FullClusterScan=true; MFTTracking.MinTrackPointsLTF=${MINCLUSTERS}; MFTTracking.MinTrackStationsLTF=1; MFTTracking.LTFclsRCut=${ROADRADIUS}; MFTTracking.LTFseed2BinWin=10; MFTTracking.MinTrackStationsCA=1; MFTTracking.ROADclsRCut=${ROADRADIUS}; MFTTracking.MinTrackPointsCA=${MINCLUSTERS};" -b --run > reco_${prefix}.log +} +export -f go_cluster_reco + diff --git a/summarise_digits.C b/summarise_digits.C new file mode 100644 index 0000000..9323cf7 --- /dev/null +++ b/summarise_digits.C @@ -0,0 +1,125 @@ +#include +#include +#include "TROOT.h" +#include "TFile.h" +#include "TTree.h" +#include "TBrowser.h" +#include "TMath.h" +#include "TRandom.h" +#include "TCanvas.h" +#include "TGraph.h" +#include +#include +#include +#include + +#include "DataFormatsITSMFT/Digit.h" +#include "DataFormatsITSMFT/ROFRecord.h" +#include "CommonDataFormat/InteractionRecord.h" + + +using namespace std; +using namespace o2::base; +using namespace o2::detectors; +using o2::itsmft::Digit; +using o2::itsmft::ROFRecord; +using BCData = o2::InteractionRecord; + +void tedshots(const UInt_t tfStart = 1, UInt_t runNumber = 503581){ + + TChain o2MFTDigitsChain("o2sim"); + + //o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_aroundtf10022.root"); // tfStart = 10021 + + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_00.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_01.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_02.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_03.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_04.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_05.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_06.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_07.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_08.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_09.root"); + + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_10.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_11.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_12.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_13.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_14.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_15.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_16.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_17.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_18.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_19.root"); + + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_20.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_21.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_22.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_23.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_24.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_25.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_26.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_27.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_28.root"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_group_tflist_29.root"); + + std::vector* mftdigit = nullptr; + std::vector* mftdigitROFs = nullptr; + o2MFTDigitsChain.SetBranchAddress("MFTDigit", &mftdigit ); + o2MFTDigitsChain.SetBranchAddress("MFTDigitROF", &mftdigitROFs); + + UInt_t numberTF = o2MFTDigitsChain.GetEntries(); + std::cout << "Number of TF = " << numberTF << std::endl; + + std::stringstream runNumberName; runNumberName << runNumber; + std::string outputFileName = "/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_summary_run"; + outputFileName += runNumberName.str() + ".root"; + + TFile *outputFile = new TFile(outputFileName.c_str(), "recreate"); + + TTree* summaryTree = new TTree("summary","the summary tree"); + UInt_t tfId = tfStart; + UInt_t orbit = 0; + UInt_t bc = 0; + UInt_t strobe = 0; + UInt_t nDigits = 0; + summaryTree->Branch("tfId", &tfId, "tfId/i"); + summaryTree->Branch("orbit", &orbit, "orbit/i"); + summaryTree->Branch("bc", &bc, "bc/i"); + summaryTree->Branch("strobe", &strobe, "strobe/i"); + summaryTree->Branch("nDigits", &nDigits, "nDigits/i"); + + for (UInt_t itf = 0; itf < numberTF; itf++) + { + tfId = tfStart + itf; + o2MFTDigitsChain.GetEvent(itf); + auto nStrobesPerTF = mftdigitROFs->size(); + auto nDigitsPerTF = mftdigit->size(); + std::cout << "TF " << tfId << std::endl; + std::cout << "- Number of RO Frames = " << nStrobesPerTF << std::endl; + std::cout << "- Number of MFT Digits = " << nDigitsPerTF << std::endl; + + strobe = 0; + for ( auto rofRec : *mftdigitROFs ) { // iterate over the ROF records + auto& bcdata = (*mftdigitROFs)[strobe].getBCData(); + orbit = bcdata.orbit; // uint32_t + bc = bcdata.bc; // uint16_t + nDigits = rofRec.getNEntries(); + if (false) { + std::cout << "\tstrobe = " << strobe << "\torbit = "<< orbit << "\tbc = " << bc << "\t\tnDigits = " << nDigits << std::endl; + } + summaryTree->Fill(); + strobe++; + } + } + summaryTree->Write(); + + TTree* inputParamTree = new TTree( "inputParam", "the input parameters" ); + inputParamTree->Branch( "runNumber", &runNumber, "runNumber/i" ); + inputParamTree->Fill(); + inputParamTree->Write(); + + outputFile->Close(); +} + diff --git a/tedshots.C b/tedshots.C new file mode 100644 index 0000000..242d960 --- /dev/null +++ b/tedshots.C @@ -0,0 +1,61 @@ +#include +#include +#include "TROOT.h" +#include "TFile.h" +#include "TTree.h" +#include "TBrowser.h" +#include "TMath.h" +#include "TRandom.h" +#include "TCanvas.h" +#include "TGraph.h" +#include +#include +#include +#include + +#include "DataFormatsITSMFT/Digit.h" +#include "DataFormatsITSMFT/ROFRecord.h" +#include "CommonDataFormat/InteractionRecord.h" + + +using namespace std; +using namespace o2::base; +using namespace o2::detectors; +using o2::itsmft::Digit; +using o2::itsmft::ROFRecord; +using BCData = o2::InteractionRecord; + +void tedshots(const int TFStart = 10021){ + + TChain o2MFTDigitsChain("o2sim"); + o2MFTDigitsChain.Add("/Users/andry/alice/commissioning/tedshots/2021-10-08/run503581/mftdigits_aroundtf10022.root"); + + std::vector* mftdigit = nullptr; + std::vector* mftdigitROFs = nullptr; + o2MFTDigitsChain.SetBranchAddress("MFTDigit", &mftdigit ); + o2MFTDigitsChain.SetBranchAddress("MFTDigitROF", &mftdigitROFs); + + Int_t numberTF = o2MFTDigitsChain.GetEntries(); + std::cout << "Number of TF = " << numberTF << std::endl; + +for (int itf = 0; itf < numberTF; itf++) +{ + o2MFTDigitsChain.GetEvent(itf); + auto nStrobes = mftdigitROFs->size(); + auto nDigits = mftdigit->size(); + std::cout << "TF " << TFStart + itf << std::endl; + std::cout << "- Number of RO Frames = " << nStrobes << std::endl; + std::cout << "- Number of MFT Digits = " << nDigits << std::endl; + + int n = 0; + for ( auto rofRec : *mftdigitROFs ) { // iterate over the ROF records + auto& bcdata = (*mftdigitROFs)[n].getBCData(); + auto orbit = bcdata.orbit; + auto bc = bcdata.bc; + std::cout << "\tstrobe = " << n << "\torbit = "<< orbit << "\tbc = " << bc << "\t\tnDigits = " << rofRec.getNEntries() << std::endl ; + n++; + } +} + +} +