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

Last change on this file since 11866 was 11864, checked in by tbretz, 15 years ago
Fixed some scaling issues which came up with the scale removed in Apply
File size: 9.6 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, sizeof(float));
151 file.SetPtrAddress("RunNumberGain", base+1, sizeof(float));
152 file.SetPtrAddress("RunNumberTriggerOffset", base+2, sizeof(float));
153 file.SetPtrAddress("BaselineMean", base+0*1024*1440+3, sizeof(float)*1024*1440);
154 file.SetPtrAddress("BaselineRms", base+1*1024*1440+3, sizeof(float)*1024*1440);
155 file.SetPtrAddress("GainMean", base+2*1024*1440+3, sizeof(float)*1024*1440);
156 file.SetPtrAddress("GainRms", base+3*1024*1440+3, sizeof(float)*1024*1440);
157 file.SetPtrAddress("TriggerOffsetMean", base+4*1024*1440+3, sizeof(float)*1024*1440);
158 file.SetPtrAddress("TriggerOffsetRms", base+5*1024*1440+3, sizeof(float)*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.