source: trunk/FACT++/src/DataWriteFits.cc@ 14580

Last change on this file since 14580 was 12806, checked in by tbretz, 13 years ago
Fixed a compiler warning because a function argument was never used.
File size: 10.8 KB
Line 
1#include "DataWriteFits.h"
2
3#include "HeadersFAD.h"
4#include "FAD.h"
5#include "Converter.h"
6
7
8using namespace std;
9
10DataWriteFits::~DataWriteFits()
11{
12 Close();
13 delete fConv;
14}
15
16template <typename T>
17 void DataWriteFits::WriteKey(const string &name, const int idx, const T &value, const string &comment)
18{
19 ostringstream str;
20 str << name << idx;
21
22 ostringstream com;
23 com << "Board " << setw(2) << idx << ": " << comment;
24
25 fFile.WriteKey(str.str(), value, com.str());
26}
27
28// --------------------------------------------------------------------------
29//
30//! DataWriteFits constructor. This is the one that should be used, not the default one (parameter-less)
31//! @param runid This parameter should probably be removed. I first thought it was the run number, but apparently it is not
32//! @param h a pointer to the RUN_HEAD structure that contains the informations relative to this run
33//
34bool DataWriteFits::Open(const RUN_HEAD* h, const FAD::RunDescription &d)
35{
36 if (fConv)
37 {
38 Error("DataWriteFits::Open called twice.");
39 return false;
40 }
41
42 const int16_t realRoiTM = (h->NroiTM >= 2*h->Nroi && h->Nroi<=512) ? h->Nroi : 0;
43
44 fFile.AddColumn('I', "EventNum");
45 fFile.AddColumn('I', "TriggerNum");
46 fFile.AddColumn('S', "TriggerType");
47 fFile.AddColumn('I', "NumBoards");
48 fFile.AddColumn('C', "Errors", 4);
49 fFile.AddColumn('I', "SoftTrig");
50 fFile.AddColumn('I', "UnixTimeUTC", 2);
51 fFile.AddColumn('I', "BoardTime", NBOARDS);
52 fFile.AddColumn('S', "StartCellData", NPIX);
53 fFile.AddColumn('S', "StartCellTimeMarker", NTMARK);
54 fFile.AddColumn('S', "Data", h->NPix*h->Nroi);
55 fFile.AddColumn('S', "TimeMarker", h->NTm*realRoiTM);
56
57 // Write length of physical pipeline (1024)
58 fConv = new Converter(Converter::ToFormat(fFile.GetColumnTypes()));
59
60 const size_t sz = (h->NPix*h->Nroi + h->NTm*realRoiTM)*2;
61 if (fConv->GetSize()-sz+4!=sizeof(EVENT))
62 {
63 ostringstream str;
64 str << "The EVENT structure size (" << sizeof(EVENT) << ") doesn't match the described FITS row (";
65 str << fConv->GetSize()-sz+4 << ")";
66 Error(str);
67 return false;
68 }
69
70 //Form filename, based on runid and run-type
71 fFileName = FormFileName("fits");
72
73 if (!fFile.OpenFile(fFileName))
74 return false;
75
76 if (!fFile.OpenTable("Events"))
77 return false;
78
79 if (!fFile.WriteDefaultKeys("fadctrl"))
80 return false;
81
82 Info("==> TODO: Write sampling frequency...");
83
84 //write header data
85 //first the "standard" keys
86 try
87 {
88 fFile.WriteKey("BLDVER", h->Version, "Builder version");
89 fFile.WriteKey("RUNID", GetRunId(), "Run number");
90// fFile.WriteKey("RUNTYPE", h->RunType, "Type of run");
91 fFile.WriteKey("NBOARD", h->NBoard, "Number of acquisition boards");
92 fFile.WriteKey("NPIX", h->NPix, "Number of pixels");
93 fFile.WriteKey("NTMARK", h->NTm, "Number of time marker channels");
94 fFile.WriteKey("NCELLS", 1024, "Maximum number of slices per pixels");
95 fFile.WriteKey("NROI", h->Nroi, "Number of slices per pixels");
96 fFile.WriteKey("NROITM", realRoiTM, "Number of slices per time-marker");
97
98 const uint16_t realOffset = (h->NroiTM > h->Nroi) ? h->NroiTM - 2*h->Nroi : 0;
99 fFile.WriteKey("TMSHIFT", realOffset, "Shift of the start of the time marker readout wrt to data");
100
101 //FIXME should we also put the start and stop time of the received data ?
102 //now the events header related variables
103 fFile.WriteKey("CAMERA", "MGeomCamFACT", "");
104 fFile.WriteKey("DAQ", "DRS4", "");
105 fFile.WriteKey("ADCRANGE", 2000, "Dynamic range in mV");
106 fFile.WriteKey("ADC", 12, "Resolution in bits");
107 fFile.WriteKey("RUNTYPE", d.name, "File type according to FAD configuration");
108
109 // Write a single key for:
110 // -----------------------
111 // Start package flag
112 // package length
113 // version number
114 // status
115 // Prescaler
116
117 // Write 40 kays for (?)
118 // Phaseshift
119 // DAC
120
121 for (int i=0; i<h->NBoard; i++)
122 {
123 const PEVNT_HEADER &hh = h->FADhead[i];
124
125 // Header values whihc won't change during the run
126 WriteKey("ID", i, hh.board_id, "Board ID");
127 WriteKey("FWVER", i, hh.version_no, "Firmware Version");
128
129 ostringstream dna;
130 dna << "0x" << hex << hh.DNA;
131 WriteKey("DNA", i, dna.str(), "Unique FPGA device identifier (DNA)");
132 }
133
134 // FIXME: Calculate average ref clock frequency
135 for (int i=0; i<h->NBoard; i++)
136 {
137 const PEVNT_HEADER &hh = h->FADhead[i];
138
139 if (hh.start_package_flag==0)
140 continue;
141
142 fFile.WriteKey("BOARD", i, "Board number for RUN, PRESC, PHASE and DAC");
143 // fFile.WriteKey("RUN", hh.runnumber, "Run number");
144 fFile.WriteKey("PRESC", hh.trigger_generator_prescaler, "Trigger generator prescaler");
145 fFile.WriteKey("PHASE", (int16_t)hh.adc_clock_phase_shift, "ADC clock phase shift");
146
147 for (int j=0; j<8; j++)
148 {
149 ostringstream dac, cmt;
150 dac << "DAC" << j;
151 cmt << "Command value for " << dac.str();
152 fFile.WriteKey(dac.str(), hh.dac[j], cmt.str());
153 }
154
155 break;
156 }
157
158 double avg = 0;
159 int cnt = 0;
160 for (int i=0; i<h->NBoard; i++)
161 {
162 const PEVNT_HEADER &hh = h->FADhead[i];
163
164 if (hh.start_package_flag==0)
165 continue;
166
167 avg += hh.REFCLK_frequency;
168 cnt ++;
169 }
170
171 // FIXME: I cannot write a double! WHY?
172 fFile.WriteKey("REFCLK", avg/cnt*2.048, "Average reference clock frequency in Hz");
173
174 fFile.WriteKey("DRSCALIB", GetDrsStep()>=0, "This file belongs to a DRS calibration");
175 if (GetDrsStep()>=0)
176 fFile.WriteKey("DRSSTEP", GetDrsStep(), "Step of the DRS calibration");
177
178 }
179 catch (const CCfits::FitsException &e)
180 {
181 Error("CCfits::Table::addKey failed in '"+fFileName+"': "+e.message());
182 return false;
183 }
184
185 // This is a workaround for the missing information in the event builder
186 fTstart[0] = 0;
187 fTstop[0] = 0;
188
189 memset(fTriggerCounter.data(), 0, fTriggerCounter.size()*sizeof(uint32_t));
190
191 //Last but not least, add header keys that will be updated when closing the file
192 return WriteFooter(NULL);
193}
194
195// --------------------------------------------------------------------------
196//
197//! This writes one event to the file
198//! @param e the pointer to the EVENT
199//
200bool DataWriteFits::WriteEvt(EVENT *e)
201{
202 if (!fFile.AddRow())
203 return false;
204
205 if (e->TriggerType && !(e->TriggerType & FAD::EventHeader::kAll))
206 fTriggerCounter[0]++;
207 else if ((e->TriggerType&FAD::EventHeader::kPedestal) && !(e->TriggerType&FAD::EventHeader::kTIM))
208 fTriggerCounter[1]++;
209 else if (e->TriggerType & FAD::EventHeader::kLPext)
210 fTriggerCounter[2]++;
211 else if (e->TriggerType & (FAD::EventHeader::kTIM|FAD::EventHeader::kPedestal))
212 fTriggerCounter[3]++;
213 else if (e->TriggerType & FAD::EventHeader::kLPint)
214 fTriggerCounter[4]++;
215 else if (e->TriggerType & FAD::EventHeader::kExt1)
216 fTriggerCounter[5]++;
217 else if (e->TriggerType & FAD::EventHeader::kExt2)
218 fTriggerCounter[6]++;
219 else
220 fTriggerCounter[7]++;
221
222 memcpy(fTstop, &e->PCTime, 2*sizeof(uint32_t));
223 if (fTstart[0]==0)
224 memcpy(fTstart, fTstop, 2*sizeof(uint32_t));
225
226 const int realRoiTM = (e->RoiTM > e->Roi) ? e->Roi : 0;
227 const size_t sz = sizeof(EVENT) + sizeof(e->StartPix)*e->Roi+sizeof(e->StartTM)*realRoiTM; //ETIENNE from RoiTm to Roi
228
229 const vector<char> data = fConv->ToFits(reinterpret_cast<char*>(e)+4, sz-4);
230
231 return fFile.WriteData(data.data(), data.size());
232}
233
234bool DataWriteFits::WriteFooter(RUN_TAIL */*rt*/)
235{
236 try
237 {
238 /*
239 fFile.WriteKey("NBEVTOK", rt ? rt->nEventsOk : uint32_t(0),
240 "How many events were written");
241
242 fFile.WriteKey("NBEVTREJ", rt ? rt->nEventsRej : uint32_t(0),
243 "How many events were rejected by SW-trig");
244
245 fFile.WriteKey("NBEVTBAD", rt ? rt->nEventsBad : uint32_t(0),
246 "How many events were rejected by Error");
247 */
248
249 //FIXME shouldn't we convert start and stop time to MjD first ?
250 //FIXME shouldn't we also add an MjD reference ?
251
252 const Time start(fTstart[0], fTstart[1]);
253 const Time stop (fTstop[0], fTstop[1]);
254
255 fFile.WriteKey("TSTARTI", uint32_t(floor(start.UnixDate())),
256 "Time when first event received (integral part)");
257 fFile.WriteKey("TSTARTF", fmod(start.UnixDate(), 1),
258 "Time when first event received (fractional part)");
259 fFile.WriteKey("TSTOPI", uint32_t(floor(stop.UnixDate())),
260 "Time when last event received (integral part)");
261 fFile.WriteKey("TSTOPF", fmod(stop.UnixDate(), 1),
262 "Time when last event received (fractional part)");
263 fFile.WriteKey("DATE-OBS", start.Iso(),
264 "Time when first event received");
265 fFile.WriteKey("DATE-END", stop.Iso(),
266 "Time when last event received");
267
268 fFile.WriteKey("NTRG", fTriggerCounter[0], "Number of physics triggers written");
269 fFile.WriteKey("NTRGPED", fTriggerCounter[1], "Number of pure pedestal triggers written");
270 fFile.WriteKey("NTRGLPE", fTriggerCounter[2], "Number of external light pulser triggers written");
271 fFile.WriteKey("NTRGTIM", fTriggerCounter[3], "Number of time calibration triggers written");
272 fFile.WriteKey("NTRGLPI", fTriggerCounter[4], "Number of internal light pulser triggers written");
273 fFile.WriteKey("NTRGEXT1", fTriggerCounter[5], "Number of triggers from ext1 written");
274 fFile.WriteKey("NTRGEXT2", fTriggerCounter[6], "Number of triggers from ext2 written");
275 fFile.WriteKey("NTRGMISC", fTriggerCounter[7], "Number of triggers belonging to no other category written");
276 }
277 catch (const CCfits::FitsException &e)
278 {
279 Error("CCfits::Table::addKey failed in '"+fFile.GetName()+"': "+e.message());
280 return false;
281 }
282 return true;
283}
284
285// --------------------------------------------------------------------------
286//
287//! Closes the file, and before this it write the TAIL data
288//! @param rt the pointer to the RUN_TAIL data structure
289//
290bool DataWriteFits::Close(RUN_TAIL *rt)
291{
292 if (!fFile.IsOpen())
293 return false;
294
295 WriteFooter(rt);
296
297 fFile.Close();
298
299 return true;
300}
Note: See TracBrowser for help on using the repository browser.