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

Last change on this file since 12064 was 12056, checked in by tbretz, 13 years ago
Added an error output in case the fits file could not be opened.
File size: 9.7 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")+1;
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 return true;
203 }
204 catch (const runtime_error &e)
205 {
206 msg.Error("Exception reading "+str+": "+e.what());
207 return false;
208 }
209}
210
211void DataCalib::WriteFits()
212{
213#ifdef HAVE_FITS
214 FitsFile file(fMsg);
215
216 file.AddColumn('I', "RunNumberBaseline");
217 file.AddColumn('I', "RunNumberGain");
218 file.AddColumn('I', "RunNumberTriggerOffset");
219 file.AddColumn('F', "BaselineMean", 1024*1440, "mV");
220 file.AddColumn('F', "BaselineRms", 1024*1440, "mV");
221 file.AddColumn('F', "GainMean", 1024*1440, "mV");
222 file.AddColumn('F', "GainRms", 1024*1440, "mV");
223 file.AddColumn('F', "TriggerOffsetMean", 1024*1440, "mV");
224 file.AddColumn('F', "TriggerOffsetRms", 1024*1440, "mV");
225
226 fFileName = FormFileName("drs.fits");
227
228 if (!file.OpenFile(fFileName))
229 return;
230
231 if (!file.OpenTable("DrsCalibration"))
232 return;
233
234 if (!file.WriteDefaultKeys("fadctrl"))
235 return;
236
237 if (!file.WriteKeyNT("STEP", fStep, "") ||
238 !file.WriteKeyNT("ADCRANGE", 2000, "Dynamic range of the ADC in mV") ||
239 !file.WriteKeyNT("DACRANGE", 2500, "Dynamic range of the DAC in mV") ||
240 !file.WriteKeyNT("ADC", 12, "Resolution of ADC in bits") ||
241 !file.WriteKeyNT("DAC", 16, "Resolution of DAC in bits") ||
242 !file.WriteKeyNT("DACLEVEL", 50000, "Applied DAC level in counts") ||
243 !file.WriteKeyNT("NBOFFSET", fNumOffset, "Number of entries for offset calibration") ||
244 !file.WriteKeyNT("NBGAIN", fNumGain/1953125, "Number of entries for gain calibration") ||
245 !file.WriteKeyNT("NBTRGOFF", fNumTrgOff, "Number of entries for trigger offset calibration") ||
246 !file.WriteKeyNT("NPIX", 1440, "Number of channels in the camera") ||
247 !file.WriteKeyNT("NROI", 1024, "Region of interest")
248 )
249 return;
250
251 vector<char> buf;
252 buf.reserve(fStats.size()*sizeof(float));
253
254 char *src = reinterpret_cast<char*>(fStats.data());
255 char *end = reinterpret_cast<char*>(fStats.data()+1024*1440*6+3);
256 char *dest = buf.data();
257
258 while (src<end)
259 {
260 reverse_copy(src, src+sizeof(float), dest);
261 src += sizeof(float);
262 dest += sizeof(float);
263 }
264
265 if (!file.AddRow())
266 return;
267
268 if (!file.WriteData(buf.data(), 1024*1440*sizeof(float)*6+3))
269 return;
270
271 ostringstream str;
272 str << "Wrote DRS calibration data (step=" << fStep << ") to '" << fFileName << "'";
273 Info(str.str());
274#endif
275}
276
277bool DataCalib::Close(RUN_TAIL *)
278{
279 if (fStep==0)
280 {
281 fOffset.assign(fSum.begin(), fSum.end());
282 fNumOffset = fNumEntries;
283
284 for (int i=0; i<1024*1440; i++)
285 fGain[i] = 4096*fNumOffset;
286
287 // Scale ADC data from 12bit to 2000mV
288 GetSampleStats(fStats.data()+3, 2000./4096);
289 reinterpret_cast<uint32_t*>(fStats.data())[0] = GetRunId();;
290 }
291 if (fStep==1)
292 {
293 fGain.assign(fSum.begin(), fSum.end());
294 fNumGain = fNumEntries;
295
296 // DAC: 0..2.5V == 0..65535
297 // V-mV: 1000
298 //fNumGain *= 2500*50000;
299 //for (int i=0; i<1024*1440; i++)
300 // fGain[i] *= 65536;
301 fNumGain *= 1953125;
302 for (int i=0; i<1024*1440; i++)
303 fGain[i] *= 1024;
304
305 // Scale ADC data from 12bit to 2000mV
306 GetSampleStats(fStats.data()+1024*1440*2+3, 2000./4096/fNumOffset);//0.5);
307 reinterpret_cast<uint32_t*>(fStats.data())[1] = GetRunId();;
308 }
309 if (fStep==2)
310 {
311 fTrgOff.assign(fSum.begin(), fSum.end());
312 fNumTrgOff = fNumEntries;
313
314 // Scale ADC data from 12bit to 2000mV
315 GetSampleStats(fStats.data()+1024*1440*4+3, 2000./4096/fNumOffset);//0.5);
316 reinterpret_cast<uint32_t*>(fStats.data())[2] = GetRunId();;
317 }
318
319 if (fStep>=0 && fStep<=2)
320 WriteFits();
321
322 fDim.Update(fStats);
323
324 fStep++;
325
326 fProcessing = false;
327
328 return true;
329}
330
331void DataCalib::Apply(int16_t *val, const int16_t *start, uint32_t roi)
332{
333 CalibData::Apply(val, start, roi,
334 fOffset.data(), fNumOffset,
335 fGain.data(), fNumGain,
336 fTrgOff.data(), fNumTrgOff);
337}
338
339void DataCalib::Apply(float *vec, int16_t *val, const int16_t *start, uint32_t roi)
340{
341 CalibData::Apply(vec, val, start, roi,
342 fOffset.data(), fNumOffset,
343 fGain.data(), fNumGain,
344 fTrgOff.data(), fNumTrgOff);
345}
346
Note: See TracBrowser for help on using the repository browser.