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

Last change on this file since 12036 was 12036, checked in by tbretz, 13 years ago
Add one to the STEP read from the FITS file.
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, 1);
151 file.SetPtrAddress("RunNumberGain", base+1, 1);
152 file.SetPtrAddress("RunNumberTriggerOffset", base+2, 1);
153 file.SetPtrAddress("BaselineMean", base+3 + 0*1024*1440, 1024*1440);
154 file.SetPtrAddress("BaselineRms", base+3 + 1*1024*1440, 1024*1440);
155 file.SetPtrAddress("GainMean", base+3 + 2*1024*1440, 1024*1440);
156 file.SetPtrAddress("GainRms", base+3 + 3*1024*1440, 1024*1440);
157 file.SetPtrAddress("TriggerOffsetMean", base+3 + 4*1024*1440, 1024*1440);
158 file.SetPtrAddress("TriggerOffsetRms", base+3 + 5*1024*1440, 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")+1;
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, "mV");
217 file.AddColumn('F', "BaselineRms", 1024*1440, "mV");
218 file.AddColumn('F', "GainMean", 1024*1440, "mV");
219 file.AddColumn('F', "GainRms", 1024*1440, "mV");
220 file.AddColumn('F', "TriggerOffsetMean", 1024*1440, "mV");
221 file.AddColumn('F', "TriggerOffsetRms", 1024*1440, "mV");
222
223 fFileName = FormFileName("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 !file.WriteKeyNT("NPIX", 1440, "Number of channels in the camera") ||
244 !file.WriteKeyNT("NROI", 1024, "Region of interest")
245 )
246 return;
247
248 vector<char> buf;
249 buf.reserve(fStats.size()*sizeof(float));
250
251 char *src = reinterpret_cast<char*>(fStats.data());
252 char *end = reinterpret_cast<char*>(fStats.data()+1024*1440*6+3);
253 char *dest = buf.data();
254
255 while (src<end)
256 {
257 reverse_copy(src, src+sizeof(float), dest);
258 src += sizeof(float);
259 dest += sizeof(float);
260 }
261
262 if (!file.AddRow())
263 return;
264
265 if (!file.WriteData(buf.data(), 1024*1440*sizeof(float)*6+3))
266 return;
267
268 ostringstream str;
269 str << "Wrote DRS calibration data (step=" << fStep << ") to '" << fFileName << "'";
270 Info(str.str());
271#endif
272}
273
274bool DataCalib::Close(RUN_TAIL *)
275{
276 if (fStep==0)
277 {
278 fOffset.assign(fSum.begin(), fSum.end());
279 fNumOffset = fNumEntries;
280
281 for (int i=0; i<1024*1440; i++)
282 fGain[i] = 4096*fNumOffset;
283
284 // Scale ADC data from 12bit to 2000mV
285 GetSampleStats(fStats.data()+3, 2000./4096);
286 reinterpret_cast<uint32_t*>(fStats.data())[0] = GetRunId();;
287 }
288 if (fStep==1)
289 {
290 fGain.assign(fSum.begin(), fSum.end());
291 fNumGain = fNumEntries;
292
293 // DAC: 0..2.5V == 0..65535
294 // V-mV: 1000
295 //fNumGain *= 2500*50000;
296 //for (int i=0; i<1024*1440; i++)
297 // fGain[i] *= 65536;
298 fNumGain *= 1953125;
299 for (int i=0; i<1024*1440; i++)
300 fGain[i] *= 1024;
301
302 // Scale ADC data from 12bit to 2000mV
303 GetSampleStats(fStats.data()+1024*1440*2+3, 2000./4096/fNumOffset);//0.5);
304 reinterpret_cast<uint32_t*>(fStats.data())[1] = GetRunId();;
305 }
306 if (fStep==2)
307 {
308 fTrgOff.assign(fSum.begin(), fSum.end());
309 fNumTrgOff = fNumEntries;
310
311 // Scale ADC data from 12bit to 2000mV
312 GetSampleStats(fStats.data()+1024*1440*4+3, 2000./4096/fNumOffset);//0.5);
313 reinterpret_cast<uint32_t*>(fStats.data())[2] = GetRunId();;
314 }
315
316 if (fStep>=0 && fStep<=2)
317 WriteFits();
318
319 fDim.Update(fStats);
320
321 fStep++;
322
323 fProcessing = false;
324
325 return true;
326}
327
328void DataCalib::Apply(int16_t *val, const int16_t *start, uint32_t roi)
329{
330 CalibData::Apply(val, start, roi,
331 fOffset.data(), fNumOffset,
332 fGain.data(), fNumGain,
333 fTrgOff.data(), fNumTrgOff);
334}
335
336void DataCalib::Apply(float *vec, int16_t *val, const int16_t *start, uint32_t roi)
337{
338 CalibData::Apply(vec, val, start, roi,
339 fOffset.data(), fNumOffset,
340 fGain.data(), fNumGain,
341 fTrgOff.data(), fNumTrgOff);
342}
343
Note: See TracBrowser for help on using the repository browser.