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

Last change on this file since 11867 was 11867, checked in by tbretz, 13 years ago
SetPtrAddress takes the number of elements not the number of bytes.
File size: 9.4 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 return false;
127
128 if (file.GetStr("TELESCOP")!="FACT")
129 {
130 msg.Error("Reading "+str+" failed: Not a valid FACT file (TELESCOP not FACT in header)");
131 return false;
132 }
133
134 if (!file.HasKey("STEP"))
135 {
136 msg.Error("Reading "+str+" failed: Is not a DRS calib file (STEP not found in header)");
137 return false;
138 }
139
140 if (file.GetNumRows()!=1)
141 {
142 msg.Error("Reading "+str+" failed: Number of rows in table is not 1.");
143 return false;
144 }
145
146 vector<float> data(1440*1024*6+3);
147
148 float *base = data.data();
149
150 file.SetPtrAddress("RunNumberBaseline", base, 1);
151 file.SetPtrAddress("RunNumberGain", base+1, 1);
152 file.SetPtrAddress("RunNumberTriggerOffset", base+2, 1);
153 file.SetPtrAddress("BaselineMean", base+0*1024*1440+3, 1024*1440);
154 file.SetPtrAddress("BaselineRms", base+1*1024*1440+3, 1024*1440);
155 file.SetPtrAddress("GainMean", base+2*1024*1440+3, 1024*1440);
156 file.SetPtrAddress("GainRms", base+3*1024*1440+3, 1024*1440);
157 file.SetPtrAddress("TriggerOffsetMean", base+4*1024*1440+3, 1024*1440);
158 file.SetPtrAddress("TriggerOffsetRms", base+5*1024*1440+3, 1024*1440);
159
160 if (!file.GetNextRow())
161 {
162 msg.Error("Reading data from "+str+" failed.");
163 return false;
164 }
165
166 fStep = file.GetUInt("STEP");
167 fNumOffset = file.GetUInt("NBOFFSET");
168 fNumGain = file.GetUInt("NBGAIN");
169 fNumTrgOff = file.GetUInt("NBTRGOFF");
170
171 memcpy(fStats.data(), base, fStats.size()*sizeof(float));
172
173 // Convert back to ADC counts: 256/125 = 4096/2000
174 // Convert back to sum (mean * num_entries)
175 for (int i=0; i<1024*1440; i++)
176 {
177 fOffset[i] = fNumOffset *256*fStats[i+1024*1440*0+3]/125;
178 fGain[i] = fNumOffset*fNumGain *256*fStats[i+1024*1440*2+3]/125;
179 fTrgOff[i] = fNumOffset*fNumTrgOff*256*fStats[i+1024*1440*4+3]/125;
180 }
181
182 // DAC: 0..2.5V == 0..65535
183 // V-mV: 1000
184 //fNumGain *= 2500*50000;
185 //for (int i=0; i<1024*1440; i++)
186 // fGain[i] *= 65536;
187 if (fStep==0)
188 {
189 for (int i=0; i<1024*1440; i++)
190 fGain[i] = fNumOffset*4096;
191 }
192 else
193 {
194 fNumGain *= 1953125;
195 for (int i=0; i<1024*1440; i++)
196 fGain[i] *= 1024;
197 }
198
199 return true;
200 }
201 catch (const runtime_error &e)
202 {
203 msg.Error("Exception reading "+str+": "+e.what());
204 return false;
205 }
206}
207
208void DataCalib::WriteFits()
209{
210#ifdef HAVE_FITS
211 FitsFile file(fMsg);
212
213 file.AddColumn('I', "RunNumberBaseline");
214 file.AddColumn('I', "RunNumberGain");
215 file.AddColumn('I', "RunNumberTriggerOffset");
216 file.AddColumn('F', "BaselineMean", 1024*1440, "V");
217 file.AddColumn('F', "BaselineRms", 1024*1440, "V");
218 file.AddColumn('F', "GainMean", 1024*1440, "V");
219 file.AddColumn('F', "GainRms", 1024*1440, "V");
220 file.AddColumn('F', "TriggerOffsetMean", 1024*1440, "V");
221 file.AddColumn('F', "TriggerOffsetRms", 1024*1440, "V");
222
223 fFileName = FormFileName(GetRunId(), "drs.fits");
224
225 if (!file.OpenFile(fFileName))
226 return;
227
228 if (!file.OpenTable("DrsCalibration"))
229 return;
230
231 if (!file.WriteDefaultKeys("fadctrl"))
232 return;
233
234 if (!file.WriteKeyNT("STEP", fStep, "") ||
235 !file.WriteKeyNT("ADCRANGE", 2000, "Dynamic range of the ADC in mV") ||
236 !file.WriteKeyNT("DACRANGE", 2500, "Dynamic range of the DAC in mV") ||
237 !file.WriteKeyNT("ADC", 12, "Resolution of ADC in bits") ||
238 !file.WriteKeyNT("DAC", 16, "Resolution of DAC in bits") ||
239 !file.WriteKeyNT("DACLEVEL", 50000, "Applied DAC level in counts") ||
240 !file.WriteKeyNT("NBOFFSET", fNumOffset, "Number of entries for offset calibration") ||
241 !file.WriteKeyNT("NBGAIN", fNumGain/1953125, "Number of entries for gain calibration") ||
242 !file.WriteKeyNT("NBTRGOFF", fNumTrgOff, "Number of entries for trigger offset calibration")
243 )
244 return;
245
246 vector<char> buf;
247 buf.reserve(fStats.size()*sizeof(float));
248
249 char *src = reinterpret_cast<char*>(fStats.data());
250 char *end = reinterpret_cast<char*>(fStats.data()+1024*1440*6+3);
251 char *dest = buf.data();
252
253 while (src<end)
254 {
255 reverse_copy(src, src+sizeof(float), dest);
256 src += sizeof(float);
257 dest += sizeof(float);
258 }
259
260 if (!file.AddRow())
261 return;
262
263 if (!file.WriteData(buf.data(), 1024*1440*sizeof(float)*6+3))
264 return;
265
266 ostringstream str;
267 str << "Wrote DRS calibration data (step=" << fStep << ") to '" << fFileName << "'";
268 Info(str.str());
269#endif
270}
271
272bool DataCalib::Close(RUN_TAIL *)
273{
274 if (fStep==0)
275 {
276 fOffset.assign(fSum.begin(), fSum.end());
277 fNumOffset = fNumEntries;
278
279 for (int i=0; i<1024*1440; i++)
280 fGain[i] = 4096*fNumOffset;
281
282 // Scale ADC data from 12bit to 2000mV
283 GetSampleStats(fStats.data()+3, 2000./4096);
284 reinterpret_cast<uint32_t*>(fStats.data())[0] = GetRunId();;
285 }
286 if (fStep==1)
287 {
288 fGain.assign(fSum.begin(), fSum.end());
289 fNumGain = fNumEntries;
290
291 // DAC: 0..2.5V == 0..65535
292 // V-mV: 1000
293 //fNumGain *= 2500*50000;
294 //for (int i=0; i<1024*1440; i++)
295 // fGain[i] *= 65536;
296 fNumGain *= 1953125;
297 for (int i=0; i<1024*1440; i++)
298 fGain[i] *= 1024;
299
300 // Scale ADC data from 12bit to 2000mV
301 GetSampleStats(fStats.data()+1024*1440*2+3, 2000./4096/fNumOffset);//0.5);
302 reinterpret_cast<uint32_t*>(fStats.data())[1] = GetRunId();;
303 }
304 if (fStep==2)
305 {
306 fTrgOff.assign(fSum.begin(), fSum.end());
307 fNumTrgOff = fNumEntries;
308
309 // Scale ADC data from 12bit to 2000mV
310 GetSampleStats(fStats.data()+1024*1440*4+3, 2000./4096/fNumOffset);//0.5);
311 reinterpret_cast<uint32_t*>(fStats.data())[2] = GetRunId();;
312 }
313
314 if (fStep>=0 && fStep<=2)
315 WriteFits();
316
317 fDim.Update(fStats);
318
319 fStep++;
320
321 fProcessing = false;
322
323 return true;
324}
325
326void DataCalib::Apply(int16_t *val, const int16_t *start, uint32_t roi)
327{
328 CalibData::Apply(val, start, roi,
329 fOffset.data(), fNumOffset,
330 fGain.data(), fNumGain,
331 fTrgOff.data(), fNumTrgOff);
332}
333
334void DataCalib::Apply(float *vec, int16_t *val, const int16_t *start, uint32_t roi)
335{
336 CalibData::Apply(vec, val, start, roi,
337 fOffset.data(), fNumOffset,
338 fGain.data(), fNumGain,
339 fTrgOff.data(), fNumTrgOff);
340}
341
Note: See TracBrowser for help on using the repository browser.