source: trunk/FACT++/src/DataCalib.cc@ 12680

Last change on this file since 12680 was 12498, checked in by tbretz, 13 years ago
Implemented commands and buttons to start a drs calibration and to reset the secondary baseline.
File size: 10.0 KB
Line 
1#include "DataCalib.h"
2
3#include "FAD.h"
4#include "FitsFile.h"
5#include "DimDescriptionService.h"
6
7#include "externals/fits.h"
8
9using namespace std;
10
11DrsCalibration DataCalib::fData;
12bool DataCalib::fProcessing = false;
13vector<float> DataCalib::fStats(1440*1024*6+160*1024*2+4);
14
15void DataCalib::Restart()
16{
17 fData.Clear();
18
19 reinterpret_cast<uint32_t*>(fStats.data())[0] = 0;
20 reinterpret_cast<uint32_t*>(fStats.data())[1] = 0;
21 reinterpret_cast<uint32_t*>(fStats.data())[2] = 0;
22 reinterpret_cast<uint32_t*>(fStats.data())[3] = 0;
23
24 int i=0;
25 while (i<1024*1440*2+4) // Set mean and RMS to 0
26 fStats[i++] = 0;
27 while (i<1024*1440*3+4)
28 fStats[i++] = 2000./4096; // Set mean to 0.5
29 while (i<1440*1024*6+160*1024*2+4)
30 fStats[i++] = 0; // Set everything else to 0
31
32 fProcessing = false;
33}
34
35bool DataCalib::ResetTrgOff(DimDescribedService &dim)
36{
37 if (fData.fStep!=3)
38 return false;
39
40 for (int i=1024*1440*3+4; i<1440*1024*6+160*1024*2+4; i++)
41 fStats[i] = 0;
42
43 reinterpret_cast<uint32_t*>(fStats.data())[0] = 0;
44 reinterpret_cast<uint32_t*>(fStats.data())[3] = 0;
45
46 fData.fStep = 1;
47 Update(dim);
48 fData.fStep = 2;
49
50 return true;
51}
52
53void DataCalib::Update(DimDescribedService &dim)
54{
55 const uint16_t roi = fData.fRoi;
56 const uint16_t ntm = fData.fNumTm;
57
58 vector<float> buf(1440*1024*6+160*1024*2+4);
59
60 memcpy(buf.data(), fStats.data(), (4*1024*1440+4)*sizeof(float));
61
62 for (int i=0; i<1440; i++)
63 {
64 memcpy(buf.data()+4+1440*1024*4 + i*1024, fStats.data()+4 + 4*1024*1440 + roi*i, roi*sizeof(float));
65 memcpy(buf.data()+4+1440*1024*5 + i*1024, fStats.data()+4 + 4*1024*1440 + roi*1440 + roi*i, roi*sizeof(float));
66 }
67
68 /*
69 for (int i=0; i<ntm; i++)
70 {
71 memcpy(buf.data()+4+1440*1024*6 + i*1024, fStats.data()+4 + 4*1024*1440 + 2*roi*1440, roi*sizeof(float));
72 memcpy(buf.data()+4+1440*1024*6+160*1024 + i*1024, fStats.data()+4 + 4*1024*1440 + 2*roi*1440+i*roi, roi*sizeof(float));
73 }*/
74
75 dim.Update(buf);
76}
77
78bool DataCalib::Open(const RUN_HEAD* h, const FAD::RunDescription &d)
79{
80 if (h->NPix != 1440)
81 {
82 fMsg.Error("Number of pixels in header not 1440.");
83 return false;
84 }
85
86 if (fProcessing)
87 {
88 fMsg.Warn("Previous DRS calibration run not yet finished!");
89 return false;
90 }
91
92 if (fData.fStep==3)
93 {
94 fMsg.Warn("DRS Calibration already finished... please restart!");
95 return false;
96 }
97
98 if (fData.fStep!=2 && h->Nroi != 1024)
99 {
100 ostringstream msg;
101 msg << "Region of interest not 1024, but " << h->Nroi << " in step " << fData.fStep << " ... as it ought to be.";
102 fMsg.Error(msg);
103 return false;
104 }
105
106 vector<uint16_t> dac(8);
107/*
108 // We don't check consistency over several boards because this is done
109 // by the eventCheck routine already
110 for (int i=0; i<h->NBoard; i++)
111 {
112 const PEVNT_HEADER &hh = h->FADhead[i];
113
114 if (hh.start_package_flag==0)
115 continue;
116
117 for (int j=0; j<8; j++)
118 dac[j] = hh.dac[j];
119
120 break;
121 }
122
123 for (int i=1; i<7; i++)
124 {
125 if (i==3 || dac[i]==dac[i+1])
126 continue;
127
128 ostringstream msg;
129 msg << "Values of DAC" << i << " (" << dac[i] << ") and DAC" << i+1 <<" (" << dac[i+1] << ") do not match... cannot take DRS calibration!";
130 fMsg.Error(msg);
131 return false;
132 }
133
134 if (fData.fStep>0)
135 {
136 for (int j=0; j<8; j++)
137 {
138 if (fData.fDAC[j]==dac[j])
139 continue;
140
141 ostringstream msg;
142 msg << "DAC value from previous run (DAC" << j << "=" << fData.fDAC[j] << ") and current run ";
143 msg << "(DAC" << j << "=" << dac[j] << ") inconsistent... cannot take DRS calibration!";
144 fMsg.Error(msg);
145 return false;
146 }
147 }
148
149 memcpy(fData.fDAC, dac.data(), 8*sizeof(uint16_t));
150*/
151 fProcessing = true;
152
153 const bool hastm = h->Nroi<=512 && h->NroiTM>=2*h->Nroi;
154
155 Reset();
156 InitSize(hastm ? 1600 : 1440, h->Nroi);
157
158 fData.fRoi = fNumSamples;
159 fData.fNumTm = hastm ? 160 : 0;
160
161 return DataWriteFits::Open(h, d);
162}
163
164bool DataCalib::WriteEvt(EVENT *e)
165{
166 // FIXME: SET StartPix to 0 if StartPix is -1
167
168 if (fData.fStep==0)
169 {
170 AddRel(e->Adc_Data, e->StartPix);
171 }
172 if (fData.fStep==1)
173 {
174 AddRel(e->Adc_Data, e->StartPix, fData.fOffset.data(), fData.fNumOffset);
175 }
176 if (fData.fStep==2)
177 {
178 AddAbs(e->Adc_Data, e->StartPix, fData.fOffset.data(), fData.fNumOffset);
179 }
180
181 return DataWriteFits::WriteEvt(e);
182}
183
184bool DataCalib::ReadFits(const string &str, MessageImp &msg)
185{
186 if (fProcessing)
187 {
188 msg.Error("Reading "+str+" failed: DRS calibration in process.");
189 return false;
190 }
191
192 try
193 {
194 const string txt = fData.ReadFitsImp(str, fStats);
195 if (txt.empty())
196 return true;
197
198 msg.Error(txt);
199 return false;
200 }
201 catch (const runtime_error &e)
202 {
203 msg.Error("Exception reading "+str+": "+e.what());
204 return false;
205 }
206}
207
208void ReverseCopy(const void *src, void *dest)
209{
210 reverse_copy(reinterpret_cast<const char*>(src),
211 reinterpret_cast<const char*>(src)+sizeof(float),
212 reinterpret_cast<char*>(dest));
213}
214
215void DataCalib::WriteFits()
216{
217#ifdef HAVE_FITS
218 FitsFile file(fMsg);
219
220 const uint16_t roi = fData.fRoi;
221 const uint16_t ntm = fData.fNumTm;
222
223 file.AddColumn('I', "RunNumberBaseline");
224 file.AddColumn('I', "RunNumberGain");
225 file.AddColumn('I', "RunNumberTriggerOffset");
226 file.AddColumn('F', "BaselineMean", 1024*1440, "mV");
227 file.AddColumn('F', "BaselineRms", 1024*1440, "mV");
228 file.AddColumn('F', "GainMean", 1024*1440, "mV");
229 file.AddColumn('F', "GainRms", 1024*1440, "mV");
230 file.AddColumn('F', "TriggerOffsetMean", roi*1440, "mV");
231 file.AddColumn('F', "TriggerOffsetRms", roi*1440, "mV");
232 file.AddColumn('F', "TriggerOffsetTMMean", roi*ntm, "mV");
233 file.AddColumn('F', "TriggerOffsetTMRms", roi*ntm, "mV");
234
235 const string filename = FormFileName("drs.fits");
236
237 if (!file.OpenFile(filename))
238 return;
239
240 if (!file.OpenTable("DrsCalibration"))
241 return;
242
243 if (!file.WriteDefaultKeys("fadctrl"))
244 return;
245
246 if (!file.WriteKeyNT("STEP", fData.fStep, "") ||
247 !file.WriteKeyNT("ADCRANGE", 2000, "Dynamic range of the ADC in mV") ||
248 !file.WriteKeyNT("DACRANGE", 2500, "Dynamic range of the DAC in mV") ||
249 !file.WriteKeyNT("ADC", 12, "Resolution of ADC in bits") ||
250 !file.WriteKeyNT("DAC", 16, "Resolution of DAC in bits") ||
251// !file.WriteKeyNT("DAC_A", fData.fDAC[0], "Level of DAC 0 in DAC counts") ||
252// !file.WriteKeyNT("DAC_B", fData.fDAC[1], "Leval of DAC 1-3 in DAC counts") ||
253// !file.WriteKeyNT("DAC_C", fData.fDAC[4], "Leval of DAC 4-7 in DAC counts") ||
254 !file.WriteKeyNT("NBOFFSET", fData.fNumOffset, "Number of entries for offset calibration") ||
255 !file.WriteKeyNT("NBGAIN", fData.fNumGain/1953125, "Number of entries for gain calibration") ||
256 !file.WriteKeyNT("NBTRGOFF", fData.fNumTrgOff, "Number of entries for trigger offset calibration") ||
257 !file.WriteKeyNT("NPIX", 1440, "Number of channels in the camera") ||
258 !file.WriteKeyNT("NTM", ntm, "Number of time marker channels") ||
259 !file.WriteKeyNT("NROI", roi, "Region of interest")
260 )
261 return;
262
263 vector<char> buf(fStats.size()*sizeof(float));
264
265 char *src = reinterpret_cast<char*>(fStats.data());
266 char *end = reinterpret_cast<char*>(fStats.data()+fStats.size());
267 char *dest = buf.data();
268
269 while (src<end)
270 {
271 reverse_copy(src, src+sizeof(float), dest);
272 src += sizeof(float);
273 dest += sizeof(float);
274 }
275
276 if (!file.AddRow())
277 return;
278
279 if (!file.WriteData(buf.data()+sizeof(float), (1440*1024*4 + 1440*roi*2 + ntm*roi*2 + 3)*sizeof(float)))
280 return;
281
282 ostringstream str;
283 str << "Wrote DRS calibration data (step=" << fData.fStep << ", roi=" << roi << ") to '" << filename << "'";
284 Info(str.str());
285#endif
286}
287
288bool DataCalib::Close(RUN_TAIL *tail)
289{
290 if (fData.fStep==0)
291 {
292 fData.fOffset.assign(fSum.begin(), fSum.end());
293 fData.fNumOffset = fNumEntries;
294
295 for (int i=0; i<1024*1440; i++)
296 fData.fGain[i] = 4096*fNumEntries;
297
298 // Scale ADC data from 12bit to 2000mV
299 GetSampleStats(fStats.data()+4, 2000./4096);
300 reinterpret_cast<uint32_t*>(fStats.data())[1] = GetRunId();;
301 }
302 if (fData.fStep==1)
303 {
304 fData.fGain.assign(fSum.begin(), fSum.end());
305 fData.fNumGain = fNumEntries;
306
307 // DAC: 0..2.5V == 0..65535 2500*50000 625*50000 625*3125
308 // V-mV: 1000 ---------- --------- --------
309 //fNumGain *= 2500*50000; 65536 16384 1024
310 //for (int i=0; i<1024*1440; i++)
311 // fGain[i] *= 65536;
312 fData.fNumGain *= 1953125;
313 for (int i=0; i<1024*1440; i++)
314 fData.fGain[i] *= 1024;
315
316 // Scale ADC data from 12bit to 2000mV
317 GetSampleStats(fStats.data()+1024*1440*2+4, 2000./4096/fData.fNumOffset);//0.5);
318 reinterpret_cast<uint32_t*>(fStats.data())[2] = GetRunId();;
319 }
320 if (fData.fStep==2)
321 {
322 fData.fTrgOff.assign(fSum.begin(), fSum.end());
323 fData.fNumTrgOff = fNumEntries;
324
325 // Scale ADC data from 12bit to 2000mV
326 GetSampleStats(fStats.data()+1024*1440*4+4, 2000./4096/fData.fNumOffset);//0.5);
327 reinterpret_cast<uint32_t*>(fStats.data())[0] = fNumSamples;
328 reinterpret_cast<uint32_t*>(fStats.data())[3] = GetRunId();
329 }
330
331 if (fData.fStep<=2)
332 WriteFits();
333
334 Update(fDim);
335
336 fData.fStep++;
337
338 fProcessing = false;
339
340 return DataWriteFits::Close(tail);
341}
Note: See TracBrowser for help on using the repository browser.