#include "DataWriteFits.h" #include "FAD.h" #include "Converter.h" using namespace std; DataWriteFits::~DataWriteFits() { Close(); delete fConv; } template void DataWriteFits::WriteKey(const string &name, const int idx, const T &value, const string &comment) { ostringstream str; str << name << idx; ostringstream com; com << "Board " << setw(2) << idx << ": " << comment; fFile.WriteKey(str.str(), value, com.str()); } // -------------------------------------------------------------------------- // //! DataWriteFits constructor. This is the one that should be used, not the default one (parameter-less) //! @param runid This parameter should probably be removed. I first thought it was the run number, but apparently it is not //! @param h a pointer to the RUN_HEAD structure that contains the informations relative to this run // bool DataWriteFits::Open(RUN_HEAD* h) { if (fConv) { Error("DataWriteFits::Open called twice."); return false; } fFile.AddColumn('I', "EventNum"); fFile.AddColumn('I', "TriggerNum"); fFile.AddColumn('S', "TriggerType"); fFile.AddColumn('I', "NumBoards"); fFile.AddColumn('C', "Errors", 4); fFile.AddColumn('I', "SoftTrig"); fFile.AddColumn('I', "PCTime", 2); fFile.AddColumn('I', "BoardTime", NBOARDS); fFile.AddColumn('S', "StartCellData", NPIX); fFile.AddColumn('S', "StartCellTimeMarker", NTMARK); fFile.AddColumn('S', "Data", h->NPix*h->Nroi); fFile.AddColumn('S', "TimeMarker", h->NTm*h->NroiTM); // Write length of physical pipeline (1024) fConv = new Converter(Converter::ToFormat(fFile.GetColumnTypes())); const size_t sz = (h->NPix*h->Nroi + h->NTm*h->NroiTM)*2; if (fConv->GetSize()-sz+4!=sizeof(EVENT)) { ostringstream str; str << "The EVENT structure size (" << sizeof(EVENT) << ") doesn't match the described FITS row ("; str << fConv->GetSize()-sz+4 << ")"; Error(str); return false; } //Form filename, based on runid and run-type fFileName = FormFileName(GetRunId(), "fits"); if (!fFile.OpenFile(fFileName)) return false; if (!fFile.OpenTable("Events")) return false; if (!fFile.WriteDefaultKeys("fadctrl")) return false; Info("==> TODO: Write sampling frequency..."); //write header data //first the "standard" keys try { fFile.WriteKey("BLDVER", h->Version, "Builder version"); fFile.WriteKey("RUNID", GetRunId(), "Run number"); fFile.WriteKey("RUNTYPE", h->RunType, "Type of run"); fFile.WriteKey("NBOARD", h->NBoard, "Number of acquisition boards"); fFile.WriteKey("NPIX", h->NPix, "Number of pixels"); fFile.WriteKey("NTMARK", h->NTm, "Number of Time marks"); fFile.WriteKey("NROI", h->Nroi, "Number of slices per pixels"); fFile.WriteKey("NROITM", h->NroiTM, "Number of slices per time-marker"); //FIXME should we also put the start and stop time of the received data ? //now the events header related variables fFile.WriteKey("CAMERA", "MGeomCamFACT", ""); fFile.WriteKey("DAQ", "DRS4", ""); fFile.WriteKey("ADCCOUNT", 2.0f, "ADC Counts per milliVolt"); // Write a single key for: // ----------------------- // Start package flag // package length // version number // status // Prescaler // Write 40 kays for (?) // Phaseshift // DAC for (int i=0; iNBoard; i++) { const PEVNT_HEADER &hh = h->FADhead[i]; // Header values whihc won't change during the run WriteKey("ID", i, hh.board_id, "Board ID"); WriteKey("DNA", i, hh.DNA, "DNA"); WriteKey("FWVER", i, hh.version_no, "Firmware Version"); } } catch (const CCfits::FitsException &e) { Error("CCfits::Table::addKey failed in "+fFileName+"': "+e.message()); return false; } /* //now the boards related keywords for (int i=0; iNBoard; i++) { const PEVNT_HEADER &hh = h->FADhead[i]; WriteKey("STPKGFG", i, hh.start_package_flag, "Start package flag"); WriteKey("PKGLEN", i, hh.package_length, "Package length"); WriteKey("STATUS", i, hh.PLLLCK, ""); // WriteKey("TRIGCRC", i, hh.trigger_crc, "Trigger CRC"); // WriteKey("TRIGTYP", i, hh.trigger_type, "Trigger type"); // WriteKey("TRIGID", i, hh.trigger_id, "Trigger ID"); // WriteKey("EVTCNTR", i, hh.fad_evt_counter, "FAD Event Counter"); // WriteKey("REFCLK", i, hh.REFCLK_frequency, "Reference Clock Frequency"); WriteKey("PHASESH", i, hh.adc_clock_phase_shift, "ADC clock phase shift"); WriteKey("TRGGEN", i, hh.number_of_triggers_to_generate, "Number of triggers to generate"); WriteKey("PRESC", i, hh.trigger_generator_prescaler, "Trigger generator prescaler"); WriteKey("RUNNB", i, hh.runnumber, "Run number"); WriteKey("TIME", i, hh.time, "Time"); // for (int j=0;jFADhead[i].drs_temperature[j], str2.str()); // } for (int j=0;jStartPix)*e->Roi+sizeof(e->StartTM)*e->RoiTM; const vector data = fConv->ToFits(reinterpret_cast(e)+4, sz-4); return fFile.WriteData(data.data(), data.size()); } bool DataWriteFits::WriteFooter(RUN_TAIL *rt) { try { fFile.WriteKey("NBEVTOK", rt ? rt->nEventsOk : uint32_t(0), "How many events were written"); fFile.WriteKey("NBEVTREJ", rt ? rt->nEventsRej : uint32_t(0), "How many events were rejected by SW-trig"); fFile.WriteKey("NBEVTBAD", rt ? rt->nEventsBad : uint32_t(0), "How many events were rejected by Error"); //FIXME shouldn't we convert start and stop time to MjD first ? //FIXME shouldn't we also add an MjD reference ? fFile.WriteKey("TSTART", rt ? rt->PCtime0 : uint32_t(0), "Time when first event received"); fFile.WriteKey("TSTOP", rt ? rt->PCtimeX : uint32_t(0), "Time when last event received"); } catch (const CCfits::FitsException &e) { Error("CCfits::Table::addKey failed in '"+fFile.GetName()+"': "+e.message()); return false; } return true; } // -------------------------------------------------------------------------- // //! Closes the file, and before this it write the TAIL data //! @param rt the pointer to the RUN_TAIL data structure // bool DataWriteFits::Close(RUN_TAIL *rt) { if (!fFile.IsOpen()) return false; WriteFooter(rt); fFile.Close(); return true; }