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

Last change on this file since 12105 was 12066, checked in by tbretz, 13 years ago
Make the newly read drs calibration only valid at the end of the function.
File size: 9.9 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
11int DataCalib::fStep = 0;
12bool DataCalib::fProcessing = false;
13
14vector<int32_t> DataCalib::fOffset(1440*1024, 0);
15vector<int64_t> DataCalib::fGain (1440*1024, 4096);
16vector<int64_t> DataCalib::fTrgOff(1440*1024, 0);
17vector<float> DataCalib::fStats (1440*1024*6+3);
18
19uint64_t DataCalib::fNumOffset = 1;
20uint64_t DataCalib::fNumGain = 2000;
21uint64_t DataCalib::fNumTrgOff = 1;
22
23void DataCalib::Restart()
24{
25 // Default gain:
26 // 0.575*[45590]*2.5V / 2^16 = 0.99999 V
27 fOffset.assign(1440*1024, 0);
28 fGain.assign (1440*1024, 4096);
29 fTrgOff.assign(1440*1024, 0);
30
31 fNumOffset = 1;
32 fNumGain = 2000;
33 fNumTrgOff = 1;
34
35 reinterpret_cast<uint32_t*>(fStats.data())[0] = 0;
36 reinterpret_cast<uint32_t*>(fStats.data())[1] = 0;
37 reinterpret_cast<uint32_t*>(fStats.data())[2] = 0;
38
39 int i=0;
40 while (i<1024*1440*2+3) // Set mean and RMS to 0
41 fStats[i++] = 0;
42 while (i<1024*1440*3+3)
43 fStats[i++] = 2000./4096; // Set mean to 0.5
44 while (i<1024*1440*6+3)
45 fStats[i++] = 0; // Set everything else to 0
46
47 fStep = 0;
48 fProcessing = false;
49}
50
51void DataCalib::Update(DimDescribedService &dim)
52{
53 dim.Update(fStats);
54}
55
56bool DataCalib::Open(RUN_HEAD* h)
57{
58 if (h->NPix != 1440)
59 {
60 fMsg.Error("Number of pixels in header not 1440.");
61 return false;
62 }
63
64 if (h->Nroi != 1024)
65 {
66 fMsg.Error("Region of interest not 1024.");
67 return false;
68 }
69
70 if (fProcessing)
71 {
72 fMsg.Warn("Previous run not yet finished!");
73 return false;
74 }
75
76 if (fStep==4)
77 {
78 fMsg.Warn("DRS Calibration already finished... please restart!");
79 return false;
80 }
81
82 fProcessing = true;
83
84 ostringstream name;
85 name << "drs-calib-" << fStep;
86 fFileName = name.str();
87
88 Reset();
89 InitSize(1440, 1024);
90
91 return true;
92}
93
94bool DataCalib::WriteEvt(EVENT *e)
95{
96 // FIXME: SET StartPix to 0 if StartPix is -1
97
98 if (fStep==0)
99 {
100 AddRel(e->Adc_Data, e->StartPix);
101 }
102 if (fStep==1)
103 {
104 AddRel(e->Adc_Data, e->StartPix, fOffset.data(), fNumOffset);
105 }
106 if (fStep==2)
107 {
108 AddAbs(e->Adc_Data, e->StartPix, fOffset.data(), fNumOffset);
109 }
110
111 return true;
112}
113
114bool DataCalib::ReadFits(const string &str, MessageImp &msg)
115{
116 if (fProcessing)
117 {
118 msg.Error("Reading "+str+" failed: DRS calibration in process.");
119 return false;
120 }
121
122 try
123 {
124 fits file(str);
125 if (!file)
126 {
127 msg.Error("Opening '"+str+"' failed: "+string(strerror(errno)));
128 return false;
129 }
130
131 if (file.GetStr("TELESCOP")!="FACT")
132 {
133 msg.Error("Reading "+str+" failed: Not a valid FACT file (TELESCOP not FACT in header)");
134 return false;
135 }
136
137 if (!file.HasKey("STEP"))
138 {
139 msg.Error("Reading "+str+" failed: Is not a DRS calib file (STEP not found in header)");
140 return false;
141 }
142
143 if (file.GetNumRows()!=1)
144 {
145 msg.Error("Reading "+str+" failed: Number of rows in table is not 1.");
146 return false;
147 }
148
149 vector<float> data(1440*1024*6+3);
150
151 float *base = data.data();
152
153 file.SetPtrAddress("RunNumberBaseline", base, 1);
154 file.SetPtrAddress("RunNumberGain", base+1, 1);
155 file.SetPtrAddress("RunNumberTriggerOffset", base+2, 1);
156 file.SetPtrAddress("BaselineMean", base+3 + 0*1024*1440, 1024*1440);
157 file.SetPtrAddress("BaselineRms", base+3 + 1*1024*1440, 1024*1440);
158 file.SetPtrAddress("GainMean", base+3 + 2*1024*1440, 1024*1440);
159 file.SetPtrAddress("GainRms", base+3 + 3*1024*1440, 1024*1440);
160 file.SetPtrAddress("TriggerOffsetMean", base+3 + 4*1024*1440, 1024*1440);
161 file.SetPtrAddress("TriggerOffsetRms", base+3 + 5*1024*1440, 1024*1440);
162
163 if (!file.GetNextRow())
164 {
165 msg.Error("Reading data from "+str+" failed.");
166 return false;
167 }
168
169 fStep = file.GetUInt("STEP");
170 fNumOffset = file.GetUInt("NBOFFSET");
171 fNumGain = file.GetUInt("NBGAIN");
172 fNumTrgOff = file.GetUInt("NBTRGOFF");
173
174 memcpy(fStats.data(), base, fStats.size()*sizeof(float));
175
176 // Convert back to ADC counts: 256/125 = 4096/2000
177 // Convert back to sum (mean * num_entries)
178 for (int i=0; i<1024*1440; i++)
179 {
180 fOffset[i] = fNumOffset *256*fStats[i+1024*1440*0+3]/125;
181 fGain[i] = fNumOffset*fNumGain *256*fStats[i+1024*1440*2+3]/125;
182 fTrgOff[i] = fNumOffset*fNumTrgOff*256*fStats[i+1024*1440*4+3]/125;
183 }
184
185 // DAC: 0..2.5V == 0..65535
186 // V-mV: 1000
187 //fNumGain *= 2500*50000;
188 //for (int i=0; i<1024*1440; i++)
189 // fGain[i] *= 65536;
190 if (fStep==0)
191 {
192 for (int i=0; i<1024*1440; i++)
193 fGain[i] = fNumOffset*4096;
194 }
195 else
196 {
197 fNumGain *= 1953125;
198 for (int i=0; i<1024*1440; i++)
199 fGain[i] *= 1024;
200 }
201
202 // Now mark the stored DRS data as "officially valid"
203 // However, this is not thread safe. It only ensures that
204 // this data is not used before it is completely and correctly
205 // read.
206 fStep++;
207
208 return true;
209 }
210 catch (const runtime_error &e)
211 {
212 msg.Error("Exception reading "+str+": "+e.what());
213 return false;
214 }
215}
216
217void DataCalib::WriteFits()
218{
219#ifdef HAVE_FITS
220 FitsFile file(fMsg);
221
222 file.AddColumn('I', "RunNumberBaseline");
223 file.AddColumn('I', "RunNumberGain");
224 file.AddColumn('I', "RunNumberTriggerOffset");
225 file.AddColumn('F', "BaselineMean", 1024*1440, "mV");
226 file.AddColumn('F', "BaselineRms", 1024*1440, "mV");
227 file.AddColumn('F', "GainMean", 1024*1440, "mV");
228 file.AddColumn('F', "GainRms", 1024*1440, "mV");
229 file.AddColumn('F', "TriggerOffsetMean", 1024*1440, "mV");
230 file.AddColumn('F', "TriggerOffsetRms", 1024*1440, "mV");
231
232 fFileName = FormFileName("drs.fits");
233
234 if (!file.OpenFile(fFileName))
235 return;
236
237 if (!file.OpenTable("DrsCalibration"))
238 return;
239
240 if (!file.WriteDefaultKeys("fadctrl"))
241 return;
242
243 if (!file.WriteKeyNT("STEP", fStep, "") ||
244 !file.WriteKeyNT("ADCRANGE", 2000, "Dynamic range of the ADC in mV") ||
245 !file.WriteKeyNT("DACRANGE", 2500, "Dynamic range of the DAC in mV") ||
246 !file.WriteKeyNT("ADC", 12, "Resolution of ADC in bits") ||
247 !file.WriteKeyNT("DAC", 16, "Resolution of DAC in bits") ||
248 !file.WriteKeyNT("DACLEVEL", 50000, "Applied DAC level in counts") ||
249 !file.WriteKeyNT("NBOFFSET", fNumOffset, "Number of entries for offset calibration") ||
250 !file.WriteKeyNT("NBGAIN", fNumGain/1953125, "Number of entries for gain calibration") ||
251 !file.WriteKeyNT("NBTRGOFF", fNumTrgOff, "Number of entries for trigger offset calibration") ||
252 !file.WriteKeyNT("NPIX", 1440, "Number of channels in the camera") ||
253 !file.WriteKeyNT("NROI", 1024, "Region of interest")
254 )
255 return;
256
257 vector<char> buf;
258 buf.reserve(fStats.size()*sizeof(float));
259
260 char *src = reinterpret_cast<char*>(fStats.data());
261 char *end = reinterpret_cast<char*>(fStats.data()+1024*1440*6+3);
262 char *dest = buf.data();
263
264 while (src<end)
265 {
266 reverse_copy(src, src+sizeof(float), dest);
267 src += sizeof(float);
268 dest += sizeof(float);
269 }
270
271 if (!file.AddRow())
272 return;
273
274 if (!file.WriteData(buf.data(), 1024*1440*sizeof(float)*6+3))
275 return;
276
277 ostringstream str;
278 str << "Wrote DRS calibration data (step=" << fStep << ") to '" << fFileName << "'";
279 Info(str.str());
280#endif
281}
282
283bool DataCalib::Close(RUN_TAIL *)
284{
285 if (fStep==0)
286 {
287 fOffset.assign(fSum.begin(), fSum.end());
288 fNumOffset = fNumEntries;
289
290 for (int i=0; i<1024*1440; i++)
291 fGain[i] = 4096*fNumOffset;
292
293 // Scale ADC data from 12bit to 2000mV
294 GetSampleStats(fStats.data()+3, 2000./4096);
295 reinterpret_cast<uint32_t*>(fStats.data())[0] = GetRunId();;
296 }
297 if (fStep==1)
298 {
299 fGain.assign(fSum.begin(), fSum.end());
300 fNumGain = fNumEntries;
301
302 // DAC: 0..2.5V == 0..65535
303 // V-mV: 1000
304 //fNumGain *= 2500*50000;
305 //for (int i=0; i<1024*1440; i++)
306 // fGain[i] *= 65536;
307 fNumGain *= 1953125;
308 for (int i=0; i<1024*1440; i++)
309 fGain[i] *= 1024;
310
311 // Scale ADC data from 12bit to 2000mV
312 GetSampleStats(fStats.data()+1024*1440*2+3, 2000./4096/fNumOffset);//0.5);
313 reinterpret_cast<uint32_t*>(fStats.data())[1] = GetRunId();;
314 }
315 if (fStep==2)
316 {
317 fTrgOff.assign(fSum.begin(), fSum.end());
318 fNumTrgOff = fNumEntries;
319
320 // Scale ADC data from 12bit to 2000mV
321 GetSampleStats(fStats.data()+1024*1440*4+3, 2000./4096/fNumOffset);//0.5);
322 reinterpret_cast<uint32_t*>(fStats.data())[2] = GetRunId();;
323 }
324
325 if (fStep>=0 && fStep<=2)
326 WriteFits();
327
328 fDim.Update(fStats);
329
330 fStep++;
331
332 fProcessing = false;
333
334 return true;
335}
336
337void DataCalib::Apply(int16_t *val, const int16_t *start, uint32_t roi)
338{
339 CalibData::Apply(val, start, roi,
340 fOffset.data(), fNumOffset,
341 fGain.data(), fNumGain,
342 fTrgOff.data(), fNumTrgOff);
343}
344
345void DataCalib::Apply(float *vec, int16_t *val, const int16_t *start, uint32_t roi)
346{
347 CalibData::Apply(vec, val, start, roi,
348 fOffset.data(), fNumOffset,
349 fGain.data(), fNumGain,
350 fTrgOff.data(), fNumTrgOff);
351}
352
Note: See TracBrowser for help on using the repository browser.