Belle II Software  release-06-02-00
ECLDspUtilities.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 // ECL
10 #include <ecl/utility/ECLDspUtilities.h>
11 #include <ecl/utility/ECLChannelMapper.h>
12 #include <ecl/dbobjects/ECLDspData.h>
13 #include <ecl/dbobjects/ECLCrystalCalib.h>
14 #include <ecl/dataobjects/ECLDigit.h>
15 // Framework
16 #include <framework/logging/Logger.h>
17 #include <framework/database/DBObjPtr.h>
18 #include <framework/database/DBArray.h>
19 #include <framework/utilities/FileSystem.h>
20 // ROOT
21 #include <TFile.h>
22 #include <TTree.h>
23 
24 using namespace Belle2;
25 using namespace ECL;
26 
28 const short ECLDSP_FORMAT_VERSION = 1;
29 
31 float ECLDspUtilities::pedfit_fg31[768] = {};
32 float ECLDspUtilities::pedfit_fg32[768] = {};
33 
38 void readEclDspCoefs(FILE* fl, void* ptr, int word_size, int word_count)
39 {
40  int read_items = fread(ptr, word_size, word_count, fl);
41  if (read_items != word_count) {
42  B2ERROR("Error reading DSP coefficients");
43  }
44 }
45 
46 ECLDspData* ECLDspUtilities::readEclDsp(const char* filename, int boardNumber)
47 {
48  FILE* fl;
49  fl = fopen(filename, "rb");
50  if (fl == nullptr) {
51  B2ERROR("Can't open file " << filename);
52  }
53 
54  ECLDspData* data = new ECLDspData(boardNumber);
55 
56  //== Do not fill data for non-existent shapers
57  int crateNum = (boardNumber - 1) / 12 + 1;
58  int shaperNum = (boardNumber - 1) % 12;
59 
60  if (shaperNum >= 8) {
61  if (crateNum >= 45) {
62  fclose(fl);
63  return data;
64  }
65  if (shaperNum >= 10) {
66  if (crateNum >= 37 && crateNum <= 44) {
67  fclose(fl);
68  return data;
69  }
70  }
71  }
72 
73  // Word size
74  const int nsiz = 2;
75  // Size of fragment to read (in words)
76  int nsiz1 = 256;
77  short int id[256];
78  int size = fread(id, nsiz, nsiz1, fl);
79  if (size != nsiz1) {
80  B2ERROR("Error reading header of DSP file");
81  }
82 
83  std::vector<short int> extraData;
84  extraData.push_back(ECLDSP_FORMAT_VERSION);
85  extraData.push_back(data->getPackerVersion());
86  data->setExtraData(extraData);
87 
88  data->setverMaj(id[8] & 0xFF);
89  data->setverMin(id[8] >> 8);
90  data->setkb(id[13] >> 8);
91  data->setka(id[13] - 256 * data->getkb());
92  data->sety0Startr(id[14] >> 8);
93  data->setkc(id[14] - 256 * data->gety0Startr());
94  data->setchiThresh(id[15]);
95  data->setk2(id[16] >> 8);
96  data->setk1(id[16] - 256 * data->getk2());
97  data->sethT(id[64]);
98  data->setlAT(id[128]);
99  data->setsT(id[192]);
100  data->setaAT(id[208]);
101 
102  std::vector<short int> f(49152), f1(49152), f31(49152),
103  f32(49152), f33(49152), f41(6144), f43(6144);
104 
105  for (int i = 0; i < 16; ++i) {
106  nsiz1 = 384;
107  readEclDspCoefs(fl, &(*(f41.begin() + i * nsiz1)), nsiz, nsiz1);
108  nsiz1 = 3072;
109  readEclDspCoefs(fl, &(*(f31.begin() + i * nsiz1)), nsiz, nsiz1);
110  readEclDspCoefs(fl, &(*(f32.begin() + i * nsiz1)), nsiz, nsiz1);
111  readEclDspCoefs(fl, &(*(f33.begin() + i * nsiz1)), nsiz, nsiz1);
112  nsiz1 = 384;
113  readEclDspCoefs(fl, &(*(f43.begin() + i * nsiz1)), nsiz, nsiz1);
114  nsiz1 = 3072;
115  readEclDspCoefs(fl, &(*(f.begin() + i * nsiz1)), nsiz, nsiz1);
116  readEclDspCoefs(fl, &(*(f1.begin() + i * nsiz1)), nsiz, nsiz1);
117  }
118  fclose(fl);
119 
120  data->setF41(f41);
121  data->setF31(f31);
122  data->setF32(f32);
123  data->setF33(f33);
124  data->setF43(f43);
125  data->setF(f);
126  data->setF1(f1);
127 
128  return data;
129 }
130 
131 void ECLDspUtilities::writeEclDsp(const char* filename, ECLDspData* data)
132 {
133  // Default header for DSP file.
134  // Words '0xABCD' are overwitten with current parameters.
135  const unsigned short DEFAULT_HEADER[256] {
136  // ECLDSP FILE.....
137  0x4543, 0x4c44, 0x5350, 0x2046, 0x494c, 0x4500, 0x0000, 0x0000,
138  0xABCD, 0xffff, 0x0000, 0x0000, 0x0000, 0xABCD, 0xABCD, 0xABCD,
139  0xABCD, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
140  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
141  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
142  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
143  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
144  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
145  0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD,
146  0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD,
147  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
148  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
149  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
150  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
151  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
152  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
153  0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD,
154  0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD,
155  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
156  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
157  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
158  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
159  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
160  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
161  0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD,
162  0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD,
163  0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD,
164  0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD, 0xABCD,
165  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
166  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
167  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
168  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
169  };
170 
171  FILE* fl;
172  fl = fopen(filename, "wb");
173  // Word size
174  const int nsiz = 2;
175  // Size of fragment to write (in words)
176  int nsiz1 = 256;
177  // modification of DEFAULT_HEADER
178  unsigned short header[256];
179 
180  int format_version = data->getExtraData()[0];
181  if (format_version > ECLDSP_FORMAT_VERSION) {
182  B2WARNING("Format version " << format_version << " is not fully supported, some data might be discarded.");
183  }
184 
185  for (int i = 0; i < 256; i++) {
186  if (i == 8) {
187  header[i] = (data->getverMin() << 8) | data->getverMaj();
188  } else if (i == 13) {
189  header[i] = (data->getkb() << 8) | data->getka();
190  } else if (i == 14) {
191  header[i] = (data->gety0Startr() << 8) | data->getkc();
192  } else if (i == 15) {
193  header[i] = data->getchiThresh();
194  } else if (i == 16) {
195  header[i] = (data->getk2() << 8) | data->getk1();
196  } else if (i >= 64 && i < 80) {
197  header[i] = data->gethT();
198  } else if (i >= 128 && i < 144) {
199  header[i] = data->getlAT();
200  } else if (i >= 192 && i < 208) {
201  header[i] = data->getsT();
202  } else if (i >= 208 && i < 224) {
203  header[i] = data->getaAT();
204  } else {
205  // Reverse bytes for header.
206  int high = (DEFAULT_HEADER[i] & 0xFF00) >> 8;
207  int low = (DEFAULT_HEADER[i] & 0x00FF);
208  header[i] = (low << 8) + high;
209  }
210  }
211 
212  int size = fwrite(header, nsiz, nsiz1, fl);
213  if (size != nsiz1) {
214  B2FATAL("Error writing header of DSP file " << filename);
215  }
216 
217  std::vector<short int> f(49152), f1(49152), f31(49152),
218  f32(49152), f33(49152), f41(6144), f43(6144);
219  data->getF41(f41);
220  data->getF31(f31);
221  data->getF32(f32);
222  data->getF33(f33);
223  data->getF43(f43);
224  data->getF(f);
225  data->getF1(f1);
226 
227  for (int i = 0; i < 16; ++i) {
228  nsiz1 = 384;
229  fwrite(&(*(f41.begin() + i * nsiz1)), nsiz, nsiz1, fl);
230  nsiz1 = 3072;
231  fwrite(&(*(f31.begin() + i * nsiz1)), nsiz, nsiz1, fl);
232  fwrite(&(*(f32.begin() + i * nsiz1)), nsiz, nsiz1, fl);
233  fwrite(&(*(f33.begin() + i * nsiz1)), nsiz, nsiz1, fl);
234  nsiz1 = 384;
235  fwrite(&(*(f43.begin() + i * nsiz1)), nsiz, nsiz1, fl);
236  nsiz1 = 3072;
237  fwrite(&(*(f.begin() + i * nsiz1)), nsiz, nsiz1, fl);
238  fwrite(&(*(f1.begin() + i * nsiz1)), nsiz, nsiz1, fl);
239  }
240  fclose(fl);
241 }
242 
243 /**********************************************/
244 /* SHAPE FITTER */
245 
246 short int* vectorsplit(std::vector<short int>& vectorFrom, int channel)
247 {
248  size_t size = vectorFrom.size();
249  if (size % 16) B2ERROR("Split is impossible!" << "Vector size" << size);
250  return (vectorFrom.data() + (size / 16) * (channel - 1));
251 }
252 
253 ECLShapeFit ECLDspUtilities::shapeFitter(int cid, std::vector<int> adc, int ttrig,
254  bool adjusted_timing)
255 {
256  ECLChannelMapper mapper;
257  mapper.initFromDB();
258 
259  //== Get mapping data
260 
261  int crate = mapper.getCrateID(cid);
262  int shaper = mapper.getShaperPosition(cid);
263  int channel = mapper.getShaperChannel(cid);
264 
265  //== Get DSP data
266 
267  int dsp_group = (crate - 1) / 18;
268  int dsp_id = (crate - 1) % 18;
269  std::string payload_name = "ECLDSPPars" + std::to_string(dsp_group);
270  DBArray<ECLDspData> dsp_data(payload_name);
271  const ECLDspData* data = dsp_data[dsp_id * 12 + shaper - 1];
272 
273  std::vector<short> vec_f; data->getF(vec_f);
274  std::vector<short> vec_f1; data->getF1(vec_f1);
275  std::vector<short> vec_fg31; data->getF31(vec_fg31);
276  std::vector<short> vec_fg32; data->getF32(vec_fg32);
277  std::vector<short> vec_fg33; data->getF33(vec_fg33);
278  std::vector<short> vec_fg41; data->getF41(vec_fg41);
279  std::vector<short> vec_fg43; data->getF43(vec_fg43);
280 
281  short* f = vectorsplit(vec_f, channel);
282  short* f1 = vectorsplit(vec_f1, channel);
283  short* fg31 = vectorsplit(vec_fg31, channel);
284  short* fg32 = vectorsplit(vec_fg32, channel);
285  short* fg33 = vectorsplit(vec_fg33, channel);
286  short* fg41 = vectorsplit(vec_fg41, channel);
287  short* fg43 = vectorsplit(vec_fg43, channel);
288 
289  int k_a = data->getka();
290  int k_b = data->getkb();
291  int k_c = data->getkc();
292  int k_1 = data->getk1();
293  int k_2 = data->getk2();
294  int k_16 = data->gety0Startr();
295  int chi_thres = data->getchiThresh();
296 
297  //== Get ADC data
298  int* y = adc.data();
299 
300  //== Get trigger time
301  int ttrig2 = ttrig - 2 * (ttrig / 8);
302 
303  //== Get thresholds
304  DBObjPtr<ECLCrystalCalib> thr_LowAmp("ECL_FPGA_LowAmp");
305  DBObjPtr<ECLCrystalCalib> thr_HitThresh("ECL_FPGA_HitThresh");
306  DBObjPtr<ECLCrystalCalib> thr_StoreDigit("ECL_FPGA_StoreDigit");
307 
308  int A0 = thr_LowAmp->getCalibVector()[cid - 1];
309  int Ahard = thr_HitThresh->getCalibVector()[cid - 1];
310  int Askip = thr_StoreDigit->getCalibVector()[cid - 1];
311 
312  //== Perform fit
313  auto result = lftda_(f, f1, fg41, fg43, fg31, fg32, fg33, y, ttrig2, A0,
314  Ahard, Askip, k_a, k_b, k_c, k_16, k_1, k_2,
315  chi_thres, adjusted_timing);
316 
317  return result;
318 }
319 
321 {
322  std::string path = FileSystem::findFile("ecl/data/ecl_pedestal_peak_fit.root");
323  TFile* file = new TFile(path.c_str(), "read");
324  if (!file->IsOpen()) {
325  B2FATAL("Unable to load coefficients for ECL pedestal fit");
326  }
327  TTree* tree = (TTree*)file->Get("dsp_coefs");
328  int nentries = tree->GetEntries();
329  float fg31_i, fg32_i;
330  tree->SetBranchAddress("fg31", &fg31_i);
331  tree->SetBranchAddress("fg32", &fg32_i);
332  //== Load DSP coefficients used in pedestal fitting
333  for (int i = 0; i < nentries; i++) {
334  tree->GetEntry(i);
335  pedfit_fg31[i] = fg31_i;
336  pedfit_fg32[i] = fg32_i;
337  }
338  file->Close();
339 
341 }
342 
344 {
346  initPedestalFit();
347  }
348 
349  ECLPedestalFit result;
350  float amp;
351 
352  //== Find maximum in the pedestal
353 
354  int ped_max = 0;
355  int ped_max_pos = 0;
356  for (int i = 0; i < 16; i++) {
357  if (adc[i] > ped_max) {
358  ped_max = adc[i];
359  ped_max_pos = i;
360  }
361  }
362 
363  // Skip fit if the peak position is on the edge of the fit region
364  if (ped_max_pos < 2 || ped_max_pos > 13) {
365  result.amp = -128;
366  return result;
367  }
368 
369  //== Get first position estimate from maximum location
370 
371  int time_index = ped_max_pos * 4 - 8;
372 
373  //== Run two iterations of chi2 minimization
374  for (int iter = 0; iter < 2; iter++) {
375  amp = 0;
376  float tim = 0;
377  for (int j = 0; j < 16; j++) {
378  amp += pedfit_fg31[j + time_index * 16] * adc[j];
379  tim += pedfit_fg32[j + time_index * 16] * adc[j];
380  }
381  tim = tim / amp;
382  time_index -= tim * 4;
383  if (time_index > 47) time_index = 47;
384  if (time_index < 0) time_index = 0;
385  }
386 
387  result.amp = amp;
388 
389  return result;
390 }
391 
Class for accessing arrays of objects in the database.
Definition: DBArray.h:26
Class for accessing objects in the database.
Definition: DBObjPtr.h:21
This object contains ECL DSP coefs – electromagnetic calorimeter digital signal processing coefficien...
Definition: ECLDspData.h:34
This class provides access to ECL channel map that is either a) Loaded from the database (see ecl/dbo...
bool initFromDB()
Initialize channel mapper from the conditions database.
int getShaperChannel(int cellID)
Get number of DSP channel in the shaper by given number of CellId.
int getShaperPosition(int cellID)
Get position of the shaper in the crate by given CellId.
int getCrateID(int iCOPPERNode, int iFINESSE, bool pcie40=false)
Get crate number by given COPPER node number and FINESSE number.
static ECLDspData * readEclDsp(const char *raw_file, int boardNumber)
Convert ECLDspData from *.dat file to Root object.
static ECLShapeFit shapeFitter(int cid, std::vector< int > adc, int ttrig, bool adjusted_timing=true)
Emulate shape fitting algorithm from ShaperDSP using algorithm from ecl/utility/src/ECLDspEmulator....
static int pedestal_fit_initialized
Flag indicating whether arrays fg31,fg32 are filled.
static ECLPedestalFit pedestalFit(std::vector< int > adc)
Fit pedestal part of the signal waveform (first 16 samples) This method will fit the first 16 samples...
static void writeEclDsp(const char *raw_file, ECLDspData *obj)
Convert ECLDspData from Root object to *.dat file.
static float pedfit_fg32[768]
DSP coefficients used to determine time in pedestalFit.
static float pedfit_fg31[768]
DSP coefficients used to determine amplitude in pedestalFit.
static void initPedestalFit()
Load DSP coefficients used in the pedestal fit function.
static std::string findFile(const std::string &path, bool silent=false)
Search for given file or directory in local or central release directory, and return absolute path if...
Definition: FileSystem.cc:145
Abstract base class for different kinds of events.
This struct is returned by the pedestalFit method that fits the first 16 samples of the waveform (ped...
ShaperDSP fit results from _lftda function.