Index: trunk/Mars/mcore/DrsCalib.h
===================================================================
--- trunk/Mars/mcore/DrsCalib.h	(revision 18119)
+++ trunk/Mars/mcore/DrsCalib.h	(revision 18122)
@@ -1197,4 +1197,105 @@
         return pos-Offset(ch, pos);
     }
+
+    std::string ReadFitsImp(const std::string &str)
+    {
+        fits file(str);
+        if (!file)
+        {
+            std::ostringstream msg;
+            msg << "Could not open file '" << str << "': " << strerror(errno);
+            return msg.str();
+        }
+
+        if (file.GetStr("TELESCOP")!="FACT")
+        {
+            std::ostringstream msg;
+            msg << "Reading '" << str << "' failed: Not a valid FACT file (TELESCOP not FACT in header)";
+            return msg.str();
+        }
+
+        if (file.GetNumRows()!=1)
+        {
+            std::ostringstream msg;
+            msg << "Reading '" << str << "' failed: Number of rows in table is not 1.";
+            return msg.str();
+        }
+
+        fNumSamples  = file.GetUInt("NROI");
+        fNumChannels = file.GetUInt("NCH");
+        fNumEntries  = file.GetUInt("NBTIME");
+
+        fStat.resize(fNumSamples*fNumChannels);
+
+        double *f = reinterpret_cast<double*>(file.SetPtrAddress("CellWidthMean"));
+        double *s = reinterpret_cast<double*>(file.SetPtrAddress("CellWidthRms"));
+
+        if (!file.GetNextRow())
+        {
+            std::ostringstream msg;
+            msg << "Reading data from " << str << " failed.";
+            return msg.str();
+        }
+
+        for (uint32_t i=0; i<fNumSamples*fNumChannels; i++)
+        {
+            fStat[i].first  = f[i];
+            fStat[i].second = s[i];
+        }
+
+        return std::string();
+    }
+
+    std::string WriteFitsImp(const std::string &filename, uint32_t night=0) const
+    {
+        ofits file(filename.c_str());
+        if (!file)
+        {
+            std::ostringstream msg;
+            msg << "Could not open file '" << filename << "': " << strerror(errno);
+            return msg.str();
+        }
+
+        file.SetDefaultKeys();
+        file.AddColumnDouble(fStat.size(), "CellWidth", "ratio", "Relative cell width");
+
+        file.SetInt("ADCRANGE", 2000,    "Dynamic range of the ADC in mV");
+        file.SetInt("DACRANGE", 2500,    "Dynamic range of the DAC in mV");
+        file.SetInt("ADC",      12,      "Resolution of ADC in bits");
+        file.SetInt("DAC",      16,      "Resolution of DAC in bits");
+        file.SetInt("NPIX",     1440,    "Number of channels in the camera");
+        file.SetInt("NTM",      0,       "Number of time marker channels");
+        file.SetInt("NROI",     fNumSamples,  "Region of interest");
+        file.SetInt("NCH",      fNumChannels, "Number of chips");
+        file.SetInt("NBTIME",   fNumEntries,  "Num of entries for time calibration");
+
+        file.WriteTableHeader("DrsCellTimes");
+        if (night>0)
+            file.SetInt("NIGHT", night, "Night as int");
+
+        /*
+        file.SetStr("DATE-OBS", fDateObs, "First event of whole DRS calibration");
+        file.SetStr("DATE-END", fDateEnd, "Last event of whole DRS calibration");
+        file.SetStr("RUN-BEG", fDateRunBeg[0], "First event of run 0");
+        file.SetStr("RUN-END", fDateRunEnd[0], "Last event of run 0");
+        */
+
+        std::vector<double> data(fNumSamples*fNumChannels*2);
+
+        for (uint32_t i=0; i<fNumSamples*fNumChannels; i++)
+        {
+            data[i] = fStat[i].first;
+            data[fNumSamples*fNumChannels+i] = fStat[i].second;
+        }
+
+        if (!file.WriteRow(data.data(), data.size()*sizeof(double)))
+        {
+            std::ostringstream msg;
+            msg << "Writing data to " << filename << " failed.";
+            return msg.str();
+        }
+
+        return std::string();
+    }
 };
 
