Index: /trunk/FACT++/gui/RawEventsViewer/RawEventsViewer.cc
===================================================================
--- /trunk/FACT++/gui/RawEventsViewer/RawEventsViewer.cc	(revision 12342)
+++ /trunk/FACT++/gui/RawEventsViewer/RawEventsViewer.cc	(revision 12343)
@@ -477,4 +477,5 @@
     drawBlur = false;
     loopCurrentEvent = false;
+    fIsDrsCalibration = false;
     SetAutoRefresh(true);
 #ifdef LOAD_RAW
@@ -1059,77 +1060,70 @@
     //calibrationLoaded = false;
 
-    MessageImp msg;
-    if (!DataCalib::ReadFits(file, msg))
-    {
-        DataCalib::Restart();
-        return;
-    }
-    /*
-
-    calibInputFile = new fits(file);
-    if (!*calibInputFile)
-    {
-        delete calibInputFile;
-        calibInputFile = NULL;
-        return;
-    }
-
-//    if (calibInputFile->HasKey("NROI"))
-//    {
-//        cout << "Looks like you're trying to load a regular raw data file as DRS calib. aborting." << endl;
-//        delete calibInputFile;
-//        calibInputFile = NULL;
-//        return;
-//    }
-
-    if (!calibInputFile->SetPtrAddress("BaselineMean", baseLineMean)){
-        cout << "Missing column " << "BaseLineMean" << " Aborting load..." << endl;
-        return;}
-    if (!calibInputFile->SetPtrAddress("GainMean", gainMean)){
-        cout << "Missing column " << "GainMean" << " Aborting load..." << endl;
-        return;}
-    if (!calibInputFile->SetPtrAddress("TriggerOffsetMean", triggerOffsetMean)){
-        cout << "Missing column " << "TriggerOffsetMean" << " Aborting load..." << endl;
-        return;}
-
-    calibInputFile->GetNextRow();
-
- //   for (int i=0;i<1024;i++)
- //       cout << gainMean[i] << " ";
- //   cout << endl << endl;
-
-    delete calibInputFile;
-*/
-    //calibrationLoaded = true;
-
-    emit newFileLoaded();
-
-    //if (calibratedCheckBox->isChecked())
+    string msg;
+    try
+    {
+        msg = fDrsCalib.ReadFitsImp(file);
+        if (msg.empty())
+        {
+            emit newFileLoaded();
+            updateGL();
+            return;
+        }
+    }
+    catch (const runtime_error &e)
+    {
+        msg = e.what();
+    }
+
+    cerr << msg << endl;
+    fDrsCalib.Clear();
+}
+
+/************************************************************
+ * PLUS EVENT
+ ************************************************************/
+void RawDataViewer::plusEvent()
+{
+    eventStepping(true);
+}
+/************************************************************
+ * MINUS EVENT
+ ************************************************************/
+void RawDataViewer::minusEvent()
+{
+    eventStepping(false);
+}
+/************************************************************
+ * SET EVENT STEP
+ ************************************************************/
+void RawDataViewer::setEventStep(int step)
+{
+    eventStep = step;
+}
+/************************************************************
+ * EVENT STEPPING
+ ************************************************************/
+
+void RawDataViewer::ApplyCalibration()
+{
+    for (int i=0;i<(1440+160)*nRoi;i++)
+        eventData[i] = (float)rawEventData[i];
+
+    if (fIsDrsCalibration)
+    {
+        fDrsCalib.Apply(eventData, rawEventData, startPix, nRoi);
+        DrsCalibrate::RemoveSpikes(eventData, nRoi);
+    }
+
+    vector<float> pixelStatsData(1440*4);
+    DrsCalibrate::GetPixelStats(pixelStatsData.data(), eventData, nRoi);
+
+    for (vector<PixelMapEntry>::const_iterator it=fPixelMap.begin(); it!=fPixelMap.end(); it++)
+        RMSvalues[it->index] = pixelStatsData[1*1440+it->hw()];
+
+    if (isVisible())
         updateGL();
 }
-/************************************************************
- * PLUS EVENT
- ************************************************************/
-void RawDataViewer::plusEvent()
-{
-    eventStepping(true);
-}
-/************************************************************
- * MINUS EVENT
- ************************************************************/
-void RawDataViewer::minusEvent()
-{
-    eventStepping(false);
-}
-/************************************************************
- * SET EVENT STEP
- ************************************************************/
-void RawDataViewer::setEventStep(int step)
-{
-    eventStep = step;
-}
-/************************************************************
- * EVENT STEPPING
- ************************************************************/
+
 void RawDataViewer::eventStepping(bool plus)
 {
@@ -1149,42 +1143,12 @@
     inputFile->GetRow(rowNum);
 //    cout << "Getting row " << rowNum << endl;
-    for (int i=0;i<(1440+160)*nRoi;i++)
-        eventData[i] = (float)rawEventData[i];
 #endif
 
-//    if (drawCalibrationLoaded && calibrationLoaded)
-//    {
-
-//    if (calibratedCheckBox->isChecked())
-        DataCalib::Apply(eventData, rawEventData, startPix, nRoi);
-        CalibData::RemoveSpikes(eventData, nRoi);
-
-        vector<float> pixelStatsData(1440*4);
-        CalibData::GetPixelStats(pixelStatsData.data(), eventData, nRoi);
-
-
-        for (vector<PixelMapEntry>::const_iterator it=fPixelMap.begin(); it!=fPixelMap.end(); it++)
-        {
-            RMSvalues[it->index] = pixelStatsData[1*1440+it->hw()];
-        }
-
-        /*
-
-        for (int i=0;i<1440;i++)
-            for (int j=0;j<nRoi;j++)
-            {
-                int realj = (j+startPix[i])%1024;
-                eventData[i*1024+j] *= 2000.f/4096.f;
-                eventData[i*1024+j] -= (baseLineMean[i*1024+realj]+triggerOffsetMean[i*1024+j]);
-                eventData[i*1024+j] /= gainMean[i*1024+realj];
-                eventData[i*1024+j] *= (50000.f/65536.f) * 2500.f;
-            }
-    }
-    */
-        if (isVisible())
-            updateGL();
+    ApplyCalibration();
+
     emit signalCurrentEvent(eventNum);
     emit signalCurrentPixel(selectedPixel);
 }
+
 /************************************************************
  * NEXT SLICE. deprec ?
@@ -1375,17 +1339,6 @@
 void UIConnector::on_calibratedCheckBox_stateChanged(int state)
 {
-    for (int i=0;i<(1440+160)*GLWindow->nRoi;i++)
-        GLWindow->eventData[i] = (float)GLWindow->rawEventData[i];
-
-//    if (GLWindow->calibratedCheckBox->isChecked())
-    if (state)
-    {
-        DataCalib::Apply(GLWindow->eventData, GLWindow->rawEventData, GLWindow->startPix, GLWindow->nRoi);
-        CalibData::RemoveSpikes(GLWindow->eventData, GLWindow->nRoi);
-    }
-
-    GLWindow->updateGL();
-
-    //drawCalibrationCheckBox->setChecked(false);
+    GLWindow->fIsDrsCalibration = state;
+    GLWindow->ApplyCalibration();
 
     on_autoScaleColor_clicked();
@@ -2220,5 +2173,4 @@
     if (!autoScaleColor->isChecked())
     {
-        /*
         GLWindow->ss[0] = 0.496;
         GLWindow->ss[1] = 0.507;
@@ -2231,5 +2183,4 @@
         colorRange3->setValue(GLWindow->ss[3]);
         colorRange4->setValue(GLWindow->ss[4]);
-        */
         return;
     }
Index: /trunk/FACT++/gui/RawEventsViewer/RawEventsViewer.h
===================================================================
--- /trunk/FACT++/gui/RawEventsViewer/RawEventsViewer.h	(revision 12342)
+++ /trunk/FACT++/gui/RawEventsViewer/RawEventsViewer.h	(revision 12343)
@@ -61,5 +61,11 @@
 
     friend class UIConnector;
+
+    DrsCalibration fDrsCalib;
+
+
 public:
+    bool fIsDrsCalibration;
+
     RawDataViewer(QWidget *parent = 0);
     ~RawDataViewer();
@@ -179,4 +185,6 @@
     double vCorr[1024];
 
+    void ApplyCalibration();
+
 //    GLfloat pixelsCoords[MAX_NUM_PIXELS][3];
 //    PixelsNeighbors neighbors[MAX_NUM_PIXELS];
Index: /trunk/FACT++/src/DataCalib.cc
===================================================================
--- /trunk/FACT++/src/DataCalib.cc	(revision 12342)
+++ /trunk/FACT++/src/DataCalib.cc	(revision 12343)
@@ -9,27 +9,11 @@
 using namespace std;
 
-int  DataCalib::fStep = 0;
+DrsCalibration DataCalib::fData;
 bool DataCalib::fProcessing = false;
-
-vector<int32_t> DataCalib::fOffset(1440*1024, 0);
-vector<int64_t> DataCalib::fGain  (1440*1024, 4096);
-vector<int64_t> DataCalib::fTrgOff(1440*1024, 0);
-vector<float>   DataCalib::fStats (1440*1024*6+3);
-
-uint64_t DataCalib::fNumOffset = 1;
-uint64_t DataCalib::fNumGain   = 2000;
-uint64_t DataCalib::fNumTrgOff = 1;
+vector<float> DataCalib::fStats(1440*1024*6+3);
 
 void DataCalib::Restart()
 {
-    // Default gain:
-    // 0.575*[45590]*2.5V / 2^16 = 0.99999 V
-    fOffset.assign(1440*1024, 0);
-    fGain.assign  (1440*1024, 4096);
-    fTrgOff.assign(1440*1024, 0);
-
-    fNumOffset = 1;
-    fNumGain   = 2000;
-    fNumTrgOff = 1;
+    fData.Clear();
 
     reinterpret_cast<uint32_t*>(fStats.data())[0] = 0;
@@ -45,5 +29,4 @@
         fStats[i++] = 0;   // Set everything else to 0
 
-    fStep = 0;
     fProcessing = false;
 }
@@ -70,9 +53,9 @@
     if (fProcessing)
     {
-        fMsg.Warn("Previous run not yet finished!");
-        return false;
-    }
-
-    if (fStep==4)
+        fMsg.Warn("Previous DRS calibration run not yet finished!");
+        return false;
+    }
+
+    if (fData.fStep==4)
     {
         fMsg.Warn("DRS Calibration already finished... please restart!");
@@ -83,5 +66,5 @@
 
     ostringstream name;
-    name << "drs-calib-" << fStep;
+    name << "drs-calib-" << fData.fStep;
     fFileName = name.str();
 
@@ -89,5 +72,5 @@
     InitSize(1440, 1024);
 
-    return true;
+    return DataWriteFits::Open(h);
 }
 
@@ -96,18 +79,18 @@
     // FIXME: SET StartPix to 0 if StartPix is -1
 
-    if (fStep==0)
+    if (fData.fStep==0)
     {
         AddRel(e->Adc_Data, e->StartPix);
     }
-    if (fStep==1)
-    {
-        AddRel(e->Adc_Data, e->StartPix, fOffset.data(), fNumOffset);
-    }
-    if (fStep==2)
-    {
-        AddAbs(e->Adc_Data, e->StartPix, fOffset.data(), fNumOffset);
-    }
-
-    return true;
+    if (fData.fStep==1)
+    {
+        AddRel(e->Adc_Data, e->StartPix, fData.fOffset.data(), fData.fNumOffset);
+    }
+    if (fData.fStep==2)
+    {
+        AddAbs(e->Adc_Data, e->StartPix, fData.fOffset.data(), fData.fNumOffset);
+    }
+
+    return DataWriteFits::WriteEvt(e);
 }
 
@@ -122,89 +105,10 @@
     try
     {
-        fits file(str);
-        if (!file)
-        {
-            msg.Error("Opening '"+str+"' failed: "+string(strerror(errno)));
-            return false;
-        }
-
-        if (file.GetStr("TELESCOP")!="FACT")
-        {
-            msg.Error("Reading "+str+" failed: Not a valid FACT file (TELESCOP not FACT in header)");
-            return false;
-        }
-
-        if (!file.HasKey("STEP"))
-        {
-            msg.Error("Reading "+str+" failed: Is not a DRS calib file (STEP not found in header)");
-            return false;
-        }
-
-        if (file.GetNumRows()!=1)
-        {
-            msg.Error("Reading "+str+" failed: Number of rows in table is not 1.");
-            return false;
-        }
-
-        vector<float> data(1440*1024*6+3);
-
-        float *base = data.data();
-
-        file.SetPtrAddress("RunNumberBaseline",      base,   1);
-        file.SetPtrAddress("RunNumberGain",          base+1, 1);
-        file.SetPtrAddress("RunNumberTriggerOffset", base+2, 1);
-        file.SetPtrAddress("BaselineMean",           base+3 + 0*1024*1440, 1024*1440);
-        file.SetPtrAddress("BaselineRms",            base+3 + 1*1024*1440, 1024*1440);
-        file.SetPtrAddress("GainMean",               base+3 + 2*1024*1440, 1024*1440);
-        file.SetPtrAddress("GainRms",                base+3 + 3*1024*1440, 1024*1440);
-        file.SetPtrAddress("TriggerOffsetMean",      base+3 + 4*1024*1440, 1024*1440);
-        file.SetPtrAddress("TriggerOffsetRms",       base+3 + 5*1024*1440, 1024*1440);
-
-        if (!file.GetNextRow())
-        {
-            msg.Error("Reading data from "+str+" failed.");
-            return false;
-        }
-
-        fStep      = file.GetUInt("STEP");
-        fNumOffset = file.GetUInt("NBOFFSET");
-        fNumGain   = file.GetUInt("NBGAIN");
-        fNumTrgOff = file.GetUInt("NBTRGOFF");
-
-        memcpy(fStats.data(), base, fStats.size()*sizeof(float));
-
-        // Convert back to ADC counts: 256/125 = 4096/2000
-        // Convert back to sum (mean * num_entries)
-        for (int i=0; i<1024*1440; i++)
-        {
-            fOffset[i] = fNumOffset           *256*fStats[i+1024*1440*0+3]/125;
-            fGain[i]   = fNumOffset*fNumGain  *256*fStats[i+1024*1440*2+3]/125;
-            fTrgOff[i] = fNumOffset*fNumTrgOff*256*fStats[i+1024*1440*4+3]/125;
-        }
-
-        // DAC:  0..2.5V == 0..65535
-        // V-mV: 1000
-        //fNumGain *= 2500*50000;
-        //for (int i=0; i<1024*1440; i++)
-        //    fGain[i] *= 65536;
-        if (fStep==0)
-        {
-            for (int i=0; i<1024*1440; i++)
-                fGain[i] = fNumOffset*4096;
-        }
-        else
-        {
-            fNumGain *= 1953125;
-            for (int i=0; i<1024*1440; i++)
-                fGain[i] *= 1024;
-        }
-
-        // Now mark the stored DRS data as "officially valid"
-        // However, this is not thread safe. It only ensures that
-        // this data is not used before it is completely and correctly
-        // read.
-        fStep++;
-
-        return true;
+        const string txt = fData.ReadFitsImp(str, fStats);
+        if (txt.empty())
+            return true;
+
+        msg.Error(txt);
+        return false;
     }
     catch (const runtime_error &e)
@@ -241,5 +145,5 @@
         return;
 
-    if (!file.WriteKeyNT("STEP",     fStep, "") ||
+    if (!file.WriteKeyNT("STEP",     fData.fStep, "") ||
         !file.WriteKeyNT("ADCRANGE", 2000,             "Dynamic range of the ADC in mV") ||
         !file.WriteKeyNT("DACRANGE", 2500,             "Dynamic range of the DAC in mV") ||
@@ -247,7 +151,7 @@
         !file.WriteKeyNT("DAC",      16,               "Resolution of DAC in bits")      ||
         !file.WriteKeyNT("DACLEVEL", 50000,            "Applied DAC level in counts")    ||
-        !file.WriteKeyNT("NBOFFSET", fNumOffset,       "Number of entries for offset calibration") ||
-        !file.WriteKeyNT("NBGAIN",   fNumGain/1953125, "Number of entries for gain calibration")   ||
-        !file.WriteKeyNT("NBTRGOFF", fNumTrgOff,       "Number of entries for trigger offset calibration") ||
+        !file.WriteKeyNT("NBOFFSET", fData.fNumOffset,       "Number of entries for offset calibration") ||
+        !file.WriteKeyNT("NBGAIN",   fData.fNumGain/1953125, "Number of entries for gain calibration")   ||
+        !file.WriteKeyNT("NBTRGOFF", fData.fNumTrgOff,       "Number of entries for trigger offset calibration") ||
         !file.WriteKeyNT("NPIX",     1440,             "Number of channels in the camera") ||
         !file.WriteKeyNT("NROI",     1024,             "Region of interest")
@@ -276,18 +180,18 @@
 
     ostringstream str;
-    str << "Wrote DRS calibration data (step=" << fStep << ") to '" << fFileName << "'";
+    str << "Wrote DRS calibration data (step=" << fData.fStep << ") to '" << fFileName << "'";
     Info(str.str());
 #endif
 }
 
-bool DataCalib::Close(RUN_TAIL *)
-{
-    if (fStep==0)
-    {
-        fOffset.assign(fSum.begin(), fSum.end());
-        fNumOffset = fNumEntries;
+bool DataCalib::Close(RUN_TAIL *tail)
+{
+    if (fData.fStep==0)
+    {
+        fData.fOffset.assign(fSum.begin(), fSum.end());
+        fData.fNumOffset = fNumEntries;
 
         for (int i=0; i<1024*1440; i++)
-            fGain[i] = 4096*fNumOffset;
+            fData.fGain[i] = 4096*fNumEntries;
 
         // Scale ADC data from 12bit to 2000mV
@@ -295,8 +199,8 @@
         reinterpret_cast<uint32_t*>(fStats.data())[0] = GetRunId();;
     }
-    if (fStep==1)
-    {
-        fGain.assign(fSum.begin(), fSum.end());
-        fNumGain = fNumEntries;
+    if (fData.fStep==1)
+    {
+        fData.fGain.assign(fSum.begin(), fSum.end());
+        fData.fNumGain = fNumEntries;
 
         // DAC:  0..2.5V == 0..65535
@@ -305,48 +209,31 @@
         //for (int i=0; i<1024*1440; i++)
         //    fGain[i] *= 65536;
-        fNumGain *= 1953125;
+        fData.fNumGain *= 1953125;
         for (int i=0; i<1024*1440; i++)
-            fGain[i] *= 1024;
+            fData.fGain[i] *= 1024;
 
         // Scale ADC data from 12bit to 2000mV
-        GetSampleStats(fStats.data()+1024*1440*2+3, 2000./4096/fNumOffset);//0.5);
+        GetSampleStats(fStats.data()+1024*1440*2+3, 2000./4096/fData.fNumOffset);//0.5);
         reinterpret_cast<uint32_t*>(fStats.data())[1] = GetRunId();;
     }
-    if (fStep==2)
-    {
-        fTrgOff.assign(fSum.begin(), fSum.end());
-        fNumTrgOff = fNumEntries;
+    if (fData.fStep==2)
+    {
+        fData.fTrgOff.assign(fSum.begin(), fSum.end());
+        fData.fNumTrgOff = fNumEntries;
 
         // Scale ADC data from 12bit to 2000mV
-        GetSampleStats(fStats.data()+1024*1440*4+3, 2000./4096/fNumOffset);//0.5);
+        GetSampleStats(fStats.data()+1024*1440*4+3, 2000./4096/fData.fNumOffset);//0.5);
         reinterpret_cast<uint32_t*>(fStats.data())[2] = GetRunId();;
     }
 
-    if (fStep>=0 && fStep<=2)
+    if (fData.fStep<=2)
         WriteFits();
 
     fDim.Update(fStats);
 
-    fStep++;
+    fData.fStep++;
 
     fProcessing = false;
 
-    return true;
-}
-
-void DataCalib::Apply(int16_t *val, const int16_t *start, uint32_t roi)
-{
-    CalibData::Apply(val, start, roi,
-                     fOffset.data(), fNumOffset,
-                     fGain.data(),   fNumGain,
-                     fTrgOff.data(), fNumTrgOff);
-}
-
-void DataCalib::Apply(float *vec, int16_t *val, const int16_t *start, uint32_t roi)
-{
-    CalibData::Apply(vec, val, start, roi,
-                     fOffset.data(), fNumOffset,
-                     fGain.data(),   fNumGain,
-                     fTrgOff.data(), fNumTrgOff);
-}
-
+    return DataWriteFits::Close(tail);
+}
Index: /trunk/FACT++/src/DataCalib.h
===================================================================
--- /trunk/FACT++/src/DataCalib.h	(revision 12342)
+++ /trunk/FACT++/src/DataCalib.h	(revision 12343)
@@ -2,26 +2,19 @@
 #define FACT_DataCalib
 
-#include "DataProcessorImp.h"
-
-using namespace std;
+#include "DataWriteFits.h"
 #include "externals/DrsCalib.h"
 
 class DimDescribedService;
 
-class DataCalib : public DataProcessorImp, CalibData
+using namespace std;
+
+class DataCalib : public DataWriteFits, public DrsCalibrate
 {
-    static std::vector<int32_t> fOffset;  /// Storage for physical baseline
-    static std::vector<int64_t> fGain;    /// Storage for baseline corrected gain
-    static std::vector<int64_t> fTrgOff;  /// Storage for logical baseline
+    static DrsCalibration fData;
 
-    static uint64_t fNumOffset;           /// Scale for physcial baseline
-    static uint64_t fNumGain;             /// Scale for gain values
-    static uint64_t fNumTrgOff;           /// Scale for logical baseline
-
-    static std::vector<float>   fStats;   /// Storage for mean and rms values
+    static std::vector<float> fStats;     /// Storage for mean and rms values
 
     /// State of the DRS calibration: Positiove numbers mean that
     /// we are in a run, negative mean that it is closed
-    static int  fStep;
     static bool fProcessing;
 
@@ -31,5 +24,5 @@
 
 public:
-    DataCalib(const std::string &path, uint32_t id, DimDescribedService &dim, MessageImp &imp) : DataProcessorImp(path, id, imp), fDim(dim)
+    DataCalib(const std::string &path, uint32_t id, DimDescribedService &dim, MessageImp &imp) : DataWriteFits(path, id, imp), fDim(dim)
     {
     }
@@ -42,10 +35,13 @@
     bool Close(RUN_TAIL * = 0);
 
-    static void Apply(int16_t *val, const int16_t *start, uint32_t roi);
-    static void Apply(float *vec, int16_t *val, const int16_t *start, uint32_t roi);
+    //static void Apply(int16_t *val, const int16_t *start, uint32_t roi);
+    static void Apply(float *vec, int16_t *val, const int16_t *start, uint32_t roi)
+    {
+        fData.Apply(vec, val, start, roi);
+    }
 
     static bool ReadFits(const string &fname, MessageImp &msg);
 
-    static bool IsValid() { return fStep>2; }
+    static bool IsValid() { return fData.IsValid(); }
 };
 
Index: /trunk/FACT++/src/EventBuilderWrapper.h
===================================================================
--- /trunk/FACT++/src/EventBuilderWrapper.h	(revision 12342)
+++ /trunk/FACT++/src/EventBuilderWrapper.h	(revision 12343)
@@ -858,8 +858,8 @@
         fDimRawData.Update(data);
 
-        CalibData::RemoveSpikes(vec, event->Roi);
+        DrsCalibrate::RemoveSpikes(vec, event->Roi);
 
         vector<float> data2(1440*4); // Mean, RMS, Max, Pos
-        CalibData::GetPixelStats(data2.data(), vec, event->Roi);
+        DrsCalibrate::GetPixelStats(data2.data(), vec, event->Roi);
 
         fDimEventData.Update(data2);
@@ -893,10 +893,10 @@
         DataCalib::Apply(data.data(), event->Adc_Data, event->StartPix, event->Roi);
 
+        DrsCalibrate::RemoveSpikes(data.data(), event->Roi);
+
         vector<float> data2(1440); // Mean, RMS, Max, Pos, first, last
-        CalibData::GetPixelMax(data2.data(), data.data(), event->Roi, 0, event->Roi-1);
-
-//        dim_lock();
+        DrsCalibrate::GetPixelMax(data2.data(), data.data(), event->Roi, 0, event->Roi-1);
+
         fDimFeedbackData.Update(data2);
-//        dim_unlock();
     }
 
Index: /trunk/Mars/mcore/DrsCalib.h
===================================================================
--- /trunk/Mars/mcore/DrsCalib.h	(revision 12342)
+++ /trunk/Mars/mcore/DrsCalib.h	(revision 12343)
@@ -1,6 +1,8 @@
-#ifndef MARS_CalibData
-#define MARS_CalibData
-
-class CalibData
+#ifndef MARS_DrsCalib
+#define MARS_DrsCalib
+
+#include "fits.h"
+
+class DrsCalibrate
 {
 protected:
@@ -10,6 +12,6 @@
     size_t fNumChannels;
 
-    vector<int64_t> fSum;
-    vector<int64_t> fSum2;
+    std::vector<int64_t> fSum;
+    std::vector<int64_t> fSum2;
 
     /*
@@ -18,5 +20,5 @@
      */
 public:
-    CalibData() : fNumEntries(0), fNumSamples(0), fNumChannels(0) { }
+    DrsCalibrate() : fNumEntries(0), fNumSamples(0), fNumChannels(0) { }
     void Reset()
     {
@@ -240,16 +242,16 @@
     }
 
-    pair<vector<double>,vector<double> > GetSampleStats() const
+    std::pair<std::vector<double>,std::vector<double> > GetSampleStats() const
     {
         if (fNumEntries==0)
-            return make_pair(vector<double>(),vector<double>());
-
-        vector<double> mean(fSum.size());
-        vector<double> error(fSum.size());
-
-        vector<int64_t>::const_iterator it = fSum.begin();
-        vector<int64_t>::const_iterator i2 = fSum2.begin();
-        vector<double>::iterator        im = mean.begin();
-        vector<double>::iterator        ie = error.begin();
+            return make_pair(std::vector<double>(),std::vector<double>());
+
+        std::vector<double> mean(fSum.size());
+        std::vector<double> error(fSum.size());
+
+        std::vector<int64_t>::const_iterator it = fSum.begin();
+        std::vector<int64_t>::const_iterator i2 = fSum2.begin();
+        std::vector<double>::iterator        im = mean.begin();
+        std::vector<double>::iterator        ie = error.begin();
 
         while (it!=fSum.end())
@@ -283,6 +285,6 @@
         }
 
-        vector<int64_t>::const_iterator it = fSum.begin();
-        vector<int64_t>::const_iterator i2 = fSum2.begin();
+        std::vector<int64_t>::const_iterator it = fSum.begin();
+        std::vector<int64_t>::const_iterator i2 = fSum2.begin();
 
         while (it!=fSum.end())
@@ -348,8 +350,159 @@
     }
 
-    const vector<int64_t> &GetSum() const { return fSum; }
+    const std::vector<int64_t> &GetSum() const { return fSum; }
 
     uint64_t GetNumEntries() const { return fNumEntries; }
 };
 
+struct DrsCalibration
+{
+    std::vector<int32_t> fOffset;
+    std::vector<int64_t> fGain;
+    std::vector<int64_t> fTrgOff;
+
+    uint64_t fNumOffset;
+    uint64_t fNumGain;
+    uint64_t fNumTrgOff;
+
+    uint32_t fStep;
+
+    DrsCalibration() :
+        fOffset(1440*1024, 0),
+        fGain(1440*1024, 4096),
+        fTrgOff(1440*1024, 0),
+        fNumOffset(1),
+        fNumGain(2000),
+        fNumTrgOff(1),
+        fStep(0)
+    {
+    }
+
+    void Clear()
+    {
+        // Default gain:
+        // 0.575*[45590]*2.5V / 2^16 = 0.99999 V
+        fOffset.assign(1440*1024, 0);
+        fGain.assign  (1440*1024, 4096);
+        fTrgOff.assign(1440*1024, 0);
+
+        fNumOffset = 1;
+        fNumGain   = 2000;
+        fNumTrgOff = 1;
+
+        fStep = 0;
+    }
+
+    string ReadFitsImp(const string &str, std::vector<float> &vec)
+    {
+        std::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.HasKey("STEP"))
+        {
+            std::ostringstream msg;
+            msg << "Reading " << str << " failed: Is not a DRS calib file (STEP not found 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();
+        }
+
+        vec.resize(1440*1024*6+3);
+
+        float *base = vec.data();
+
+        file.SetPtrAddress("RunNumberBaseline",      base,   1);
+        file.SetPtrAddress("RunNumberGain",          base+1, 1);
+        file.SetPtrAddress("RunNumberTriggerOffset", base+2, 1);
+        file.SetPtrAddress("BaselineMean",           base+0*1024*1440+3, 1024*1440);
+        file.SetPtrAddress("BaselineRms",            base+1*1024*1440+3, 1024*1440);
+        file.SetPtrAddress("GainMean",               base+2*1024*1440+3, 1024*1440);
+        file.SetPtrAddress("GainRms",                base+3*1024*1440+3, 1024*1440);
+        file.SetPtrAddress("TriggerOffsetMean",      base+4*1024*1440+3, 1024*1440);
+        file.SetPtrAddress("TriggerOffsetRms",       base+5*1024*1440+3, 1024*1440);
+
+        if (!file.GetNextRow())
+        {
+            std::ostringstream msg;
+            msg << "Reading data from " << str << " failed.";
+            return msg.str();
+        }
+
+        fStep      = file.GetUInt("STEP");
+        fNumOffset = file.GetUInt("NBOFFSET");
+        fNumGain   = file.GetUInt("NBGAIN");
+        fNumTrgOff = file.GetUInt("NBTRGOFF");
+
+        fOffset.resize(1024*1440);
+        fGain.resize(1024*1440);
+        fTrgOff.resize(1024*1440);
+
+        // Convert back to ADC counts: 256/125 = 4096/2000
+        // Convert back to sum (mean * num_entries)
+        for (int i=0; i<1024*1440; i++)
+        {
+            fOffset[i] = fNumOffset           *256*base[i+1024*1440*0+3]/125;
+            fGain[i]   = fNumOffset*fNumGain  *256*base[i+1024*1440*2+3]/125;
+            fTrgOff[i] = fNumOffset*fNumTrgOff*256*base[i+1024*1440*4+3]/125;
+        }
+
+        // DAC:  0..2.5V == 0..65535
+        // V-mV: 1000
+        //fNumGain *= 2500*50000;
+        //for (int i=0; i<1024*1440; i++)
+        //    fGain[i] *= 65536;
+        if (fStep==0)
+        {
+            for (int i=0; i<1024*1440; i++)
+                fGain[i] = fNumOffset*4096;
+        }
+        else
+        {
+            fNumGain *= 1953125;
+            for (int i=0; i<1024*1440; i++)
+                fGain[i] *= 1024;
+        }
+
+        // Now mark the stored DRS data as "officially valid"
+        // However, this is not thread safe. It only ensures that
+        // this data is not used before it is completely and correctly
+        // read.
+        fStep++;
+
+        return string();
+    }
+    string ReadFitsImp(const string &str)
+    {
+        std::vector<float> vec;
+        return ReadFitsImp(str, vec);
+    }
+
+    bool IsValid() { return fStep>2; }
+
+    void Apply(float *vec, int16_t *val, const int16_t *start, uint32_t roi)
+    {
+        DrsCalibrate::Apply(vec, val, start, roi,
+                            fOffset.data(), fNumOffset,
+                            fGain.data(),   fNumGain,
+                            fTrgOff.data(), fNumTrgOff);
+
+    }
+};
+
 #endif
