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