Changeset 10949
- Timestamp:
- 06/09/11 14:28:21 (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/FACT++/src/EventBuilderWrapper.h
r10942 r10949 15 15 #include <boost/date_time/posix_time/posix_time_types.hpp> 16 16 17 #include <CCfits/CCfits> 18 17 19 #include "EventBuilder.h" 18 20 … … 21 23 extern int CloseRunFile(uint32_t runId, uint32_t closeTime); 22 24 } 25 26 class DataFileImp 27 { 28 uint32_t fRunId; 29 30 public: 31 DataFileImp(uint32_t id) : fRunId(id) { } 32 33 virtual bool OpenFile(uint32_t runid, RUN_HEAD* h) = 0; 34 virtual bool Write(EVENT *) = 0; 35 virtual bool Close(RUN_TAIL * = 0) = 0; 36 37 uint32_t GetRunId() const { return fRunId; } 38 }; 39 40 41 #include "FAD.h" 42 43 class DataFileRaw : public DataFileImp 44 { 45 public: 46 DataFileRaw(uint32_t id) : DataFileImp(id) { } 47 ~DataFileRaw() { Close(); } 48 49 virtual bool OpenFile(uint32_t, RUN_HEAD* ) { return true; } 50 virtual bool Write(EVENT *) { return true; } 51 virtual bool Close(RUN_TAIL * = 0) { return true; } 52 }; 53 54 55 class DataFileFits : public DataFileImp 56 { 57 CCfits::FITS* fFile; /// The pointer to the CCfits FITS file 58 CCfits::Table* fTable; /// The pointer to the CCfits binary table 59 60 uint64_t fNumRows; ///the number of rows that have been written already to the FITS file. 61 uint32_t fRoi; ///the number of rows that have been written already to the FITS file. 62 63 public: 64 DataFileFits(uint32_t runid) : DataFileImp(runid), fFile(0) 65 { 66 } 67 68 // -------------------------------------------------------------------------- 69 // 70 //! Default destructor 71 //! The Fits file SHOULD have been closed already, otherwise the informations 72 //! related to the RUN_TAIL will NOT be written to the file. 73 // 74 ~DataFileFits() { Close(); } 75 76 // -------------------------------------------------------------------------- 77 // 78 //! Add a new column to the vectors storing the column data. 79 //! @param names the vector of string storing the columns names 80 //! @param types the vector of string storing the FITS data format 81 //! @param numElems the number of elements in this column 82 //! @param type the char describing the FITS data format 83 //! @param name the name of the particular column to be added. 84 // 85 inline void AddColumnEntry(vector<string>& names, vector<string>& types, int numElems, char type, string name) 86 { 87 names.push_back(name); 88 89 ostringstream str; 90 if (numElems != 1) 91 str << numElems; 92 str << type; 93 types.push_back(str.str()); 94 } 95 96 // -------------------------------------------------------------------------- 97 // 98 //! Writes a single header key entry 99 //! @param name the name of the key 100 //! @param value its value 101 //! @param comment the comment associated to that key 102 // 103 //FIXME this function is a duplicate from the class Fits. should we try to merge it ? 104 template <typename T> 105 void WriteKey(const string &name, const T &value, const string &comment) 106 { 107 try 108 { 109 fTable->addKey(name, value, comment); 110 } 111 catch (CCfits::FitsException e) 112 { 113 ostringstream str; 114 str << "Could not add header key "; 115 //TODO pipe the error message somewhere 116 } 117 } 118 119 template <typename T> 120 void WriteKey(const string &name, const int idx, const T &value, const string &comment) 121 { 122 ostringstream str; 123 str << name << idx; 124 125 WriteKey(str.str(), value, comment); 126 } 127 128 // -------------------------------------------------------------------------- 129 // 130 //! This creates an appropriate file name for a particular run number and type 131 //! @param runNumber the run number for which a filename is to be created 132 //! @param runType an int describing the kind of run. 0=Data, 1=Pedestal, 2=Calibration, 3=Calibrated data 133 //! @param extension a string containing the extension to be appened to the file name 134 // 135 string FormFileName(uint32_t runNumber, uint32_t runType, string extension) 136 { 137 //TODO where am I supposed to get the base directory from ? 138 //TODO also, for creating subsequent directories, should I use the functions from the dataLogger ? 139 string baseDirectory = "./Run"; 140 ostringstream result; 141 result << baseDirectory; 142 result << Time::fmt("/%Y/%m/%d/") << (Time() - boost::posix_time::time_duration(12,0,0)); 143 result << setfill('0') << setw(8) << runNumber; 144 result << "_001_"; 145 switch (runType) 146 { 147 case 0: 148 result << 'D'; 149 break; 150 case 1: 151 result << 'P'; 152 break; 153 case 2: 154 result << 'C'; 155 break; 156 case 3: 157 result << 'Y'; 158 break; 159 default: 160 //TODO pipe this error message to the appropriate error stream 161 cout << "Error unexpected event" << endl; 162 }; 163 result << "_data." << extension; 164 165 return result.str(); 166 } 167 168 // -------------------------------------------------------------------------- 169 // 170 //! DataFileFits constructor. This is the one that should be used, not the default one (parameter-less) 171 //! @param runid This parameter should probably be removed. I first thought it was the run number, but apparently it is not 172 //! @param h a pointer to the RUN_HEAD structure that contains the informations relative to this run 173 // 174 bool OpenFile(uint32_t /*runid*/, RUN_HEAD* h) 175 { 176 //Form filename, based on runid and run-type 177 string fileName = FormFileName(h->FADhead[0].runnumber, h->RunType, "fits"); 178 179 //create the FITS object 180 try 181 { 182 fFile = new CCfits::FITS(fileName, CCfits::RWmode::Write); 183 } 184 catch (CCfits::FitsException e) 185 { 186 ostringstream str; 187 str << "Could not open FITS file " << fileName << " reason: " << e.message(); 188 //TODO display the message somewhere 189 190 return false; 191 } 192 193 //create columns according to header 194 ostringstream arrayTypes; 195 196 // uint32_t EventNum ; // EventNumber as from FTM 197 // uint16_t TriggerType ; // Trigger Type from FTM 198 // uint32_t SoftTrig ; // SoftTrigger Info (TBD) 199 // uint32_t PCTime ; // when did event start to arrive at PC 200 // uint32_t BoardTime[NBOARDS];// 201 // int16_t StartPix[NPIX]; // First Channel per Pixel (Pixels sorted according Software ID) ; -1 if not filled 202 // int16_t StartTM[NTMARK]; // First Channel for TimeMark (sorted Hardware ID) ; -1 if not filled 203 // uint16_t Adc_Data[]; // final length defined by malloc .... 204 205 vector<string> colNames; 206 vector<string> dataTypes; 207 AddColumnEntry(colNames, dataTypes, 1, 'V', "EventNum"); 208 AddColumnEntry(colNames, dataTypes, 1, 'U', "TriggerType"); 209 AddColumnEntry(colNames, dataTypes, 1, 'V', "SoftTrig"); 210 AddColumnEntry(colNames, dataTypes, 1, 'V', "PCTime"); 211 AddColumnEntry(colNames, dataTypes, NBOARDS, 'V', "BoardTime"); 212 AddColumnEntry(colNames, dataTypes, NPIX, 'I', "StartPix"); 213 AddColumnEntry(colNames, dataTypes, NTMARK, 'I', "StartTM"); 214 AddColumnEntry(colNames, dataTypes, NPIX*h->Nroi, 'U', "Data"); 215 216 fRoi = h->Nroi; 217 218 //actually create the table 219 try 220 { 221 fTable = fFile->addTable("Events", 0, colNames, dataTypes); 222 if (fTable->rows() != 0) 223 { 224 ostringstream str; 225 str << "Error: table created on the fly looks non-empty."; 226 //TODO giev the error text to some error handler 227 //FIXME I guess that this error checking is useless. remove it for performances. 228 } 229 } 230 catch(CCfits::FitsException e) 231 { 232 ostringstream str; 233 str << "Could not create FITS table " << "Events" << " in file " << fileName << " reason: " << e.message(); 234 //TODO give the error text to some error handler 235 236 Close(); 237 return false; 238 } 239 240 //write header data 241 //first the "standard" keys 242 string stringValue; 243 WriteKey("EXTREL", 1.0f, "Release Number"); 244 WriteKey("TELESCOP", "FACT", "Telescope that acquired this data"); 245 WriteKey("ORIGIN", "ISDC", "Institution that wrote the file"); 246 WriteKey("CREATOR", "FACT++ Event Builder", "Program that wrote this file"); 247 248 stringValue = Time().GetAsStr(); 249 stringValue[10]= 'T'; 250 WriteKey("DATE", stringValue, "File creation data"); 251 WriteKey("TIMESYS", "TT", "Time frame system"); 252 WriteKey("TIMEUNIT", "d", "Time unit"); 253 WriteKey("TIMEREF", "UTC", "Time reference frame"); 254 //FIXME should we also put the start and stop time of the received data ? 255 //now the events header related variables 256 WriteKey("VERSION", h->Version, "Builder version"); 257 WriteKey("RUNTYPE", h->RunType, "Type of run"); 258 WriteKey("NBOARD", h->NBoard, "Number of acquisition boards"); 259 WriteKey("NPIX", h->NPix, "Number of pixels"); 260 WriteKey("NTM", h->NTm, "Number of Time marks"); 261 WriteKey("NROI", h->Nroi, "Number of slices per pixels"); 262 263 //now the boards related keywords 264 for (int i=0; i<h->NBoard; i++) 265 { 266 const PEVNT_HEADER &hh = h->FADhead[i]; 267 268 WriteKey("STPKGFG", i, hh.start_package_flag, 269 "Start package flag"); 270 271 WriteKey("PKGLEN", i, hh.package_length, 272 "Package length"); 273 274 WriteKey("VERNO", i, hh.version_no, 275 "Version number"); 276 277 WriteKey("PLLLCK", i, hh.PLLLCK, 278 ""); 279 /* 280 WriteKey("TRIGCRC", i, hh.trigger_crc, 281 "Trigger CRC"); 282 283 WriteKey("TRIGTYP", i, hh.trigger_type, 284 "Trigger type"); 285 286 WriteKey("TRIGID", i, hh.trigger_id, 287 "Trigger ID"); 288 289 WriteKey("EVTCNTR", i, hh.fad_evt_counter, 290 "FAD Event Counter"); 291 */ 292 WriteKey("REFCLK", i, hh.REFCLK_frequency, 293 "Reference Clock Frequency"); 294 295 WriteKey("BOARDID", i, hh.board_id, 296 "Board ID"); 297 298 WriteKey("PHASESH", i, hh.adc_clock_phase_shift, 299 "ADC clock phase shift"); 300 301 //WriteKey("TRGGEN", i, hh.number_of_triggers_to_generate, 302 // "Number of triggers to generate"); 303 304 WriteKey("PRESC", i, hh.trigger_generator_prescaler, 305 "Trigger generator prescaler"); 306 307 WriteKey("DNA", i, hh.DNA, "DNA"); 308 WriteKey("TIME", i, hh.time, "Time"); 309 WriteKey("RUNNB", i, hh.runnumber, "Run number"); 310 /* 311 for (int j=0;j<NTemp;j++) 312 { 313 str.str(""); str2.str(""); 314 str << "DRS_T" << i << j; 315 str2 << "DRS temperature #" << i << " " << j; 316 WriteKey(str.str(), h->FADhead[i].drs_temperature[j], str2.str()); 317 } 318 */ 319 for (int j=0;j<NDAC;j++) 320 WriteKey("DAC", i*NDAC+j, hh.dac[j], "DAC"); 321 322 //Last but not least, add header keys that will be updated when closing the file 323 WriteFooter(NULL); 324 } 325 326 return true; 327 } 328 329 330 int WriteColumns(size_t &start, size_t size, void *e) 331 { 332 int status = 0; 333 fits_write_tblbytes(fFile->fitsPointer(), fNumRows, start, size, reinterpret_cast<unsigned char*>(e), &status); 334 start += size; 335 return status; 336 } 337 338 // -------------------------------------------------------------------------- 339 // 340 //! This writes one event to the file 341 //! @param e the pointer to the EVENT 342 // 343 virtual bool Write(EVENT *e) 344 { 345 //FIXME As discussed earlier, we do not swap the bytes yet. 346 fTable->makeThisCurrent(); 347 348 //insert a new row 349 int status(0); 350 if (fits_insert_rows(fTable->fitsPointer(), fNumRows, 1, &status)) 351 { 352 ostringstream str; 353 str << "Could not insert a row in fits file"; 354 //TODO pipe this error message to the appropriate error stream 355 } 356 fNumRows++; 357 358 const int sh = sizeof(PEVNT_HEADER)-1; 359 360 // column size pointer 361 size_t col = 1; 362 if (!WriteColumns(col, sh + NPIX*fRoi*2, e)) 363 return true; 364 365 //TODO output an error 366 return false; 367 368 /* 369 //write the data, chunk by chunk 370 //FIXME hard-coded size corresponds to current variables of the event, in bytes. 371 //FIXME no padding was taken into account. Because smallest member is 2 bytes, I don't think that this should be a problem. 372 const long sizeInBytesOfEventBeforePointers = 16; 373 374 long col = 1; 375 if (FitsWriteTblBytes(col, sizeInBytesOfEventBeforePointers, e)) 376 { 377 //TODO output an error 378 return false; 379 } 380 if (FitsWriteTblBytes(col, NBOARDS*2, e->BoardTime)) 381 { 382 //TODO output an error 383 return false; 384 } 385 if (FitsWriteTblBytes(col, NPIX*2, e->StartPix)) 386 { 387 //TODO output an error 388 return false; 389 } 390 if (FitsWriteTblBytes(col, NTMARK*2, e->StartTM)) 391 { 392 //TODO output an error 393 return false; 394 } 395 if (FitsWriteTblBytes(col, NPIX*fRoi*2, e->Adc_Data)) 396 { 397 //TODO output an error 398 return false; 399 } 400 return true;*/ 401 } 402 403 void WriteFooter(RUN_TAIL *rt) 404 { 405 //write final header keys 406 fTable->makeThisCurrent(); 407 408 WriteKey("NBEVTOK", rt ? rt->nEventsOk : uint32_t(0), 409 "How many events were written"); 410 411 WriteKey("NBEVTREJ", rt ? rt->nEventsRej : uint32_t(0), 412 "How many events were rejected by SW-trig"); 413 414 WriteKey("NBEVTBAD", rt ? rt->nEventsBad : uint32_t(0), 415 "How many events were rejected by Error"); 416 417 //FIXME shouldn't we convert start and stop time to MjD first ? 418 //FIXME shouldn't we also add an MjD reference ? 419 420 WriteKey("TSTART", rt ? rt->PCtime0 : uint32_t(0), 421 "Time when first event received"); 422 423 WriteKey("TSTOP", rt ? rt->PCtimeX : uint32_t(0), 424 "Time when last event received"); 425 } 426 427 // -------------------------------------------------------------------------- 428 // 429 //! Closes the file, and before this it write the TAIL data 430 //! @param rt the pointer to the RUN_TAIL data structure 431 // 432 virtual bool Close(RUN_TAIL *rt = 0) 433 { 434 if (!fFile) 435 return false; 436 437 WriteFooter(rt); 438 439 delete fFile; 440 fFile = NULL; 441 442 return true; 443 } 444 445 }; 23 446 24 447 class EventBuilderWrapper … … 212 635 // -------------- Mapped event builder callbacks ------------------ 213 636 214 class DataFileImp215 {216 uint32_t fRunId;217 218 public:219 DataFileImp(uint32_t id) : fRunId(id) { }220 221 virtual bool Write() = 0;222 virtual bool Close() = 0;223 224 uint32_t GetRunId() const { return fRunId; }225 };226 227 228 class DataFileRaw : public DataFileImp229 {230 public:231 DataFileRaw(uint32_t id) : DataFileImp(id) { }232 ~DataFileRaw() { Close(); }233 234 virtual bool Write() { return true; }235 virtual bool Close() { return true; }236 };237 238 class DataFileFits : public DataFileImp239 {240 public:241 DataFileFits(uint32_t id) :DataFileImp(id) { }242 ~DataFileFits() { Close(); }243 244 virtual bool Write() { return true; }245 virtual bool Close() { return true; }246 };247 248 637 vector<DataFileImp*> fFiles; 249 638 … … 259 648 { 260 649 // Check if file already exists... 261 DataFileImp *file = NULL; 650 DataFileImp *file = fFitsFormat ? 651 static_cast<DataFileImp*>(new DataFileFits(runid)) : 652 static_cast<DataFileImp*>(new DataFileRaw(runid)); 653 262 654 try 263 655 { 264 file = fFitsFormat ? 265 static_cast<DataFileImp*>(new DataFileFits(runid)) : 266 static_cast<DataFileImp*>(new DataFileRaw(runid)); 656 if (!file->OpenFile(runid, h)) 657 return 0; 267 658 } 268 659 catch (const exception &e) … … 311 702 cout << " tim=" << e->PCTime << endl; 312 703 313 if (!file->Write( ))704 if (!file->Write(e)) 314 705 return -1; 315 706 … … 333 724 } 334 725 335 int runClose(FileHandle_t handler, RUN_TAIL * , size_t)726 int runClose(FileHandle_t handler, RUN_TAIL *tail, size_t) 336 727 { 337 728 DataFileImp *file = reinterpret_cast<DataFileImp*>(handler); … … 357 748 //fDimFiles.update(); 358 749 359 const bool rc = file->Close( );750 const bool rc = file->Close(tail); 360 751 if (!rc) 361 752 { … … 395 786 void factOut(int severity, int err, char *message) 396 787 { 397 //replace(message, message+strlen(message), '\n', ' ');398 399 788 // FIXME: Make the output to the console stream thread-safe 400 789 ostringstream str;
Note:
See TracChangeset
for help on using the changeset viewer.