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

Last change on this file since 12477 was 12477, checked in by tbretz, 13 years ago
Moved RunDescription to HeadersFAD, added it as a second argument to Open and write the run-type to the header.
File size: 8.0 KB
Line 
1#include "DataWriteFits.h"
2
3#include "HeadersFAD.h"
4#include "FAD.h"
5#include "Converter.h"
6
7using namespace std;
8
9DataWriteFits::~DataWriteFits()
10{
11 Close();
12 delete fConv;
13}
14
15template <typename T>
16 void DataWriteFits::WriteKey(const string &name, const int idx, const T &value, const string &comment)
17{
18 ostringstream str;
19 str << name << idx;
20
21 ostringstream com;
22 com << "Board " << setw(2) << idx << ": " << comment;
23
24 fFile.WriteKey(str.str(), value, com.str());
25}
26
27// --------------------------------------------------------------------------
28//
29//! DataWriteFits constructor. This is the one that should be used, not the default one (parameter-less)
30//! @param runid This parameter should probably be removed. I first thought it was the run number, but apparently it is not
31//! @param h a pointer to the RUN_HEAD structure that contains the informations relative to this run
32//
33bool DataWriteFits::Open(const RUN_HEAD* h, const FAD::RunDescription &d)
34{
35 if (fConv)
36 {
37 Error("DataWriteFits::Open called twice.");
38 return false;
39 }
40
41 fFile.AddColumn('I', "EventNum");
42 fFile.AddColumn('I', "TriggerNum");
43 fFile.AddColumn('S', "TriggerType");
44 fFile.AddColumn('I', "NumBoards");
45 fFile.AddColumn('C', "Errors", 4);
46 fFile.AddColumn('I', "SoftTrig");
47 fFile.AddColumn('I', "UnixTimeUTC", 2);
48 fFile.AddColumn('I', "BoardTime", NBOARDS);
49 fFile.AddColumn('S', "StartCellData", NPIX);
50 fFile.AddColumn('S', "StartCellTimeMarker", NTMARK);
51 fFile.AddColumn('S', "Data", h->NPix*h->Nroi);
52
53 int16_t realRoiTM = (h->NroiTM > h->Nroi) ? h->Nroi : 0;
54 fFile.AddColumn('S', "TimeMarker", h->NTm*realRoiTM);//ETIENNE TM);
55
56 // Write length of physical pipeline (1024)
57
58 fConv = new Converter(Converter::ToFormat(fFile.GetColumnTypes()));
59
60 const size_t sz = (h->NPix*h->Nroi + h->NTm*realRoiTM)*2;//ETIENNE TM)*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 marks");
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"); //ETIENNE from NroiTMm to Nroi
97
98 const uint16_t realOffset = (h->NroiTM > h->Nroi) ? h->NroiTM - 2*h->Nroi : 0;
99 fFile.WriteKey("OFFSET", realOffset, "Offset between pixels ROI and TM ROi"); //ETIENNE added
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("TYPE", d.name, "File type according to FAD configuration (Config database)");
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("DNA", i, hh.DNA, "DNA");
128 WriteKey("FWVER", i, hh.version_no, "Firmware Version");
129 }
130
131 // FIXME: Calculate average ref clock frequency
132 for (int i=0; i<h->NBoard; i++)
133 {
134 const PEVNT_HEADER &hh = h->FADhead[i];
135
136 if (hh.start_package_flag==0)
137 continue;
138
139 fFile.WriteKey("BOARD", i, "Board number for RUN, PRESC, PHASE and DAC");
140 fFile.WriteKey("RUN", hh.runnumber, "Run number");
141 fFile.WriteKey("PRESC", hh.trigger_generator_prescaler, "Trigger generator prescaler");
142 fFile.WriteKey("PHASE", (int16_t)hh.adc_clock_phase_shift, "ADC clock phase shift");
143
144 for (int j=0; j<8; j++)
145 {
146 ostringstream dac, cmt;
147 dac << "DAC" << j;
148 cmt << "Command value for " << dac.str();
149 fFile.WriteKey(dac.str(), hh.dac[j], cmt.str());
150 }
151
152 break;
153 }
154
155 double avg = 0;
156 int cnt = 0;
157 for (int i=0; i<h->NBoard; i++)
158 {
159 const PEVNT_HEADER &hh = h->FADhead[i];
160
161 if (hh.start_package_flag==0)
162 continue;
163
164 avg += hh.REFCLK_frequency;
165 cnt ++;
166 }
167
168 // FIXME: I cannot write a double! WHY?
169 fFile.WriteKey("REFCLK", avg/cnt, "Average reference clock frequency in Hz");
170 }
171 catch (const CCfits::FitsException &e)
172 {
173 Error("CCfits::Table::addKey failed in '"+fFileName+"': "+e.message());
174 return false;
175 }
176
177 //Last but not least, add header keys that will be updated when closing the file
178 return WriteFooter(NULL);
179}
180
181// --------------------------------------------------------------------------
182//
183//! This writes one event to the file
184//! @param e the pointer to the EVENT
185//
186bool DataWriteFits::WriteEvt(EVENT *e)
187{
188 if (!fFile.AddRow())
189 return false;
190 int realRoiTM = (e->RoiTM > e->Roi) ? e->Roi : 0;
191 const size_t sz = sizeof(EVENT) + sizeof(e->StartPix)*e->Roi+sizeof(e->StartTM)*realRoiTM; //ETIENNE from RoiTm to Roi
192
193 const vector<char> data = fConv->ToFits(reinterpret_cast<char*>(e)+4, sz-4);
194
195 return fFile.WriteData(data.data(), data.size());
196}
197
198bool DataWriteFits::WriteFooter(RUN_TAIL *rt)
199{
200 try
201 {
202 /*
203 fFile.WriteKey("NBEVTOK", rt ? rt->nEventsOk : uint32_t(0),
204 "How many events were written");
205
206 fFile.WriteKey("NBEVTREJ", rt ? rt->nEventsRej : uint32_t(0),
207 "How many events were rejected by SW-trig");
208
209 fFile.WriteKey("NBEVTBAD", rt ? rt->nEventsBad : uint32_t(0),
210 "How many events were rejected by Error");
211 */
212
213 //FIXME shouldn't we convert start and stop time to MjD first ?
214 //FIXME shouldn't we also add an MjD reference ?
215
216 fFile.WriteKey("TSTART", rt ? rt->PCtime0 : uint32_t(0),
217 "Time when first event received");
218
219 fFile.WriteKey("TSTOP", rt ? rt->PCtimeX : uint32_t(0),
220 "Time when last event received");
221 }
222 catch (const CCfits::FitsException &e)
223 {
224 Error("CCfits::Table::addKey failed in '"+fFile.GetName()+"': "+e.message());
225 return false;
226 }
227 return true;
228}
229
230// --------------------------------------------------------------------------
231//
232//! Closes the file, and before this it write the TAIL data
233//! @param rt the pointer to the RUN_TAIL data structure
234//
235bool DataWriteFits::Close(RUN_TAIL *rt)
236{
237 if (!fFile.IsOpen())
238 return false;
239
240 WriteFooter(rt);
241
242 fFile.Close();
243
244 return true;
245}
Note: See TracBrowser for help on using the repository browser.