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

Last change on this file since 12148 was 12148, checked in by tbretz, 13 years ago
Added writing of more information into header.
File size: 7.2 KB
Line 
1#include "DataWriteFits.h"
2
3#include "FAD.h"
4#include "Converter.h"
5
6using namespace std;
7
8DataWriteFits::~DataWriteFits()
9{
10 Close();
11 delete fConv;
12}
13
14template <typename T>
15 void DataWriteFits::WriteKey(const string &name, const int idx, const T &value, const string &comment)
16{
17 ostringstream str;
18 str << name << idx;
19
20 ostringstream com;
21 com << "Board " << setw(2) << idx << ": " << comment;
22
23 fFile.WriteKey(str.str(), value, com.str());
24}
25
26// --------------------------------------------------------------------------
27//
28//! DataWriteFits constructor. This is the one that should be used, not the default one (parameter-less)
29//! @param runid This parameter should probably be removed. I first thought it was the run number, but apparently it is not
30//! @param h a pointer to the RUN_HEAD structure that contains the informations relative to this run
31//
32bool DataWriteFits::Open(RUN_HEAD* h)
33{
34 if (fConv)
35 {
36 Error("DataWriteFits::Open called twice.");
37 return false;
38 }
39
40 fFile.AddColumn('I', "EventNum");
41 fFile.AddColumn('I', "TriggerNum");
42 fFile.AddColumn('S', "TriggerType");
43 fFile.AddColumn('I', "NumBoards");
44 fFile.AddColumn('C', "Errors", 4);
45 fFile.AddColumn('I', "SoftTrig");
46 fFile.AddColumn('I', "PCTime", 2);
47 fFile.AddColumn('I', "BoardTime", NBOARDS);
48 fFile.AddColumn('S', "StartCellData", NPIX);
49 fFile.AddColumn('S', "StartCellTimeMarker", NTMARK);
50 fFile.AddColumn('S', "Data", h->NPix*h->Nroi);
51 fFile.AddColumn('S', "TimeMarker", h->NTm*h->NroiTM);
52
53 // Write length of physical pipeline (1024)
54
55 fConv = new Converter(Converter::ToFormat(fFile.GetColumnTypes()));
56
57 const size_t sz = (h->NPix*h->Nroi + h->NTm*h->NroiTM)*2;
58 if (fConv->GetSize()-sz+4!=sizeof(EVENT))
59 {
60 ostringstream str;
61 str << "The EVENT structure size (" << sizeof(EVENT) << ") doesn't match the described FITS row (";
62 str << fConv->GetSize()-sz+4 << ")";
63 Error(str);
64 return false;
65 }
66
67 //Form filename, based on runid and run-type
68 fFileName = FormFileName("fits");
69
70 if (!fFile.OpenFile(fFileName))
71 return false;
72
73 if (!fFile.OpenTable("Events"))
74 return false;
75
76 if (!fFile.WriteDefaultKeys("fadctrl"))
77 return false;
78
79 Info("==> TODO: Write sampling frequency...");
80
81 //write header data
82 //first the "standard" keys
83 try
84 {
85 fFile.WriteKey("BLDVER", h->Version, "Builder version");
86 fFile.WriteKey("RUNID", GetRunId(), "Run number");
87 fFile.WriteKey("RUNTYPE", h->RunType, "Type of run");
88 fFile.WriteKey("NBOARD", h->NBoard, "Number of acquisition boards");
89 fFile.WriteKey("NPIX", h->NPix, "Number of pixels");
90 fFile.WriteKey("NTMARK", h->NTm, "Number of Time marks");
91 fFile.WriteKey("NROI", h->Nroi, "Number of slices per pixels");
92 fFile.WriteKey("NROITM", h->NroiTM, "Number of slices per time-marker");
93
94 //FIXME should we also put the start and stop time of the received data ?
95 //now the events header related variables
96 fFile.WriteKey("CAMERA", "MGeomCamFACT", "");
97 fFile.WriteKey("DAQ", "DRS4", "");
98 fFile.WriteKey("ADCRANGE", 2000, "Dynamic range in mV");
99 fFile.WriteKey("ADC", 12, "Resolution in bits");
100
101
102 // Write a single key for:
103 // -----------------------
104 // Start package flag
105 // package length
106 // version number
107 // status
108 // Prescaler
109
110 // Write 40 kays for (?)
111 // Phaseshift
112 // DAC
113
114 for (int i=0; i<h->NBoard; i++)
115 {
116 const PEVNT_HEADER &hh = h->FADhead[i];
117
118 // Header values whihc won't change during the run
119 WriteKey("ID", i, hh.board_id, "Board ID");
120 WriteKey("DNA", i, hh.DNA, "DNA");
121 WriteKey("FWVER", i, hh.version_no, "Firmware Version");
122 }
123
124 // FIXME: Calculate average ref clock frequency
125 for (int i=0; i<h->NBoard; i++)
126 {
127 const PEVNT_HEADER &hh = h->FADhead[i];
128
129 if (hh.start_package_flag==0)
130 continue;
131
132 fFile.WriteKey("RUN", hh.runnumber, "Run number");
133 fFile.WriteKey("PRESC", hh.trigger_generator_prescaler, "Trigger generator prescaler");
134 fFile.WriteKey("PHASE", hh.adc_clock_phase_shift, "ADC clock phase shift");
135
136 for (int j=0; j<8; j++)
137 {
138 ostringstream dac;
139 dac << "DAC" << j;
140 fFile.WriteKey(dac.str(), hh.dac[j], "DAC command value");
141 }
142
143 break;
144 }
145
146 double avg = 0;
147 int cnt = 0;
148 for (int i=0; i<h->NBoard; i++)
149 {
150 const PEVNT_HEADER &hh = h->FADhead[i];
151
152 if (hh.start_package_flag==0)
153 continue;
154
155 avg += hh.REFCLK_frequency;
156 cnt ++;
157 }
158
159 fFile.WriteKey("REFCLK", avg/cnt, "Average reference clock frequency in Hz");
160 }
161 catch (const CCfits::FitsException &e)
162 {
163 Error("CCfits::Table::addKey failed in "+fFileName+"': "+e.message());
164 return false;
165 }
166
167 //Last but not least, add header keys that will be updated when closing the file
168 return WriteFooter(NULL);
169}
170
171// --------------------------------------------------------------------------
172//
173//! This writes one event to the file
174//! @param e the pointer to the EVENT
175//
176bool DataWriteFits::WriteEvt(EVENT *e)
177{
178 if (!fFile.AddRow())
179 return false;
180
181 const size_t sz = sizeof(EVENT) + sizeof(e->StartPix)*e->Roi+sizeof(e->StartTM)*e->RoiTM;
182
183 const vector<char> data = fConv->ToFits(reinterpret_cast<char*>(e)+4, sz-4);
184
185 return fFile.WriteData(data.data(), data.size());
186}
187
188bool DataWriteFits::WriteFooter(RUN_TAIL *rt)
189{
190 try
191 {
192 /*
193 fFile.WriteKey("NBEVTOK", rt ? rt->nEventsOk : uint32_t(0),
194 "How many events were written");
195
196 fFile.WriteKey("NBEVTREJ", rt ? rt->nEventsRej : uint32_t(0),
197 "How many events were rejected by SW-trig");
198
199 fFile.WriteKey("NBEVTBAD", rt ? rt->nEventsBad : uint32_t(0),
200 "How many events were rejected by Error");
201 */
202
203 //FIXME shouldn't we convert start and stop time to MjD first ?
204 //FIXME shouldn't we also add an MjD reference ?
205
206 fFile.WriteKey("TSTART", rt ? rt->PCtime0 : uint32_t(0),
207 "Time when first event received");
208
209 fFile.WriteKey("TSTOP", rt ? rt->PCtimeX : uint32_t(0),
210 "Time when last event received");
211 }
212 catch (const CCfits::FitsException &e)
213 {
214 Error("CCfits::Table::addKey failed in '"+fFile.GetName()+"': "+e.message());
215 return false;
216 }
217 return true;
218}
219
220// --------------------------------------------------------------------------
221//
222//! Closes the file, and before this it write the TAIL data
223//! @param rt the pointer to the RUN_TAIL data structure
224//
225bool DataWriteFits::Close(RUN_TAIL *rt)
226{
227 if (!fFile.IsOpen())
228 return false;
229
230 WriteFooter(rt);
231
232 fFile.Close();
233
234 return true;
235}
Note: See TracBrowser for help on using the repository browser.