Index: trunk/FACT++/src/DataCalib.cc
===================================================================
--- trunk/FACT++/src/DataCalib.cc	(revision 11828)
+++ trunk/FACT++/src/DataCalib.cc	(revision 11829)
@@ -114,4 +114,10 @@
 bool DataCalib::ReadFits(const string &str, MessageImp &msg)
 {
+    if (fProcessing)
+    {
+        msg.Error("Reading "+str+" failed: DRS calibration in process.");
+        return false;
+    }
+
     try
     {
@@ -158,87 +164,20 @@
         }
 
-        fStep = file.GetUInt("STEP");
+        fStep      = file.GetUInt("STEP");
+        fNumOffset = file.GetUInt("NBOFFSET");
+        fNumGain   = file.GetUInt("NBGAIN");
+        fNumTrgOff = file.GetUInt("NBTRGOFF");
 
         memcpy(fStats.data(), base, fStats.size()*sizeof(float));
 
-        return true;
-    }
-    catch (const runtime_error &e)
-    {
-        msg.Error("Exception reading "+str+": "+e.what());
-        return false;
-    }
-}
-
-void DataCalib::WriteFits()
-{
-#ifdef HAVE_FITS
-    FitsFile file(fMsg);
-
-    file.AddColumn('I', "RunNumberBaseline");
-    file.AddColumn('I', "RunNumberGain");
-    file.AddColumn('I', "RunNumberTriggerOffset");
-    file.AddColumn('F', "BaselineMean", 1024*1440);
-    file.AddColumn('F', "BaselineRms", 1024*1440);
-    file.AddColumn('F', "GainMean", 1024*1440);
-    file.AddColumn('F', "GainRms", 1024*1440);
-    file.AddColumn('F', "TriggerOffsetMean", 1024*1440);
-    file.AddColumn('F', "TriggerOffsetRms", 1024*1440);
-
-    fFileName = FormFileName(GetRunId(), "drs.fits");
-
-    if (!file.OpenFile(fFileName))
-        return;
-
-    if (!file.OpenTable("DrsCalibration"))
-        return;
-
-    if (!file.WriteDefaultKeys("fadctrl"))
-        return;
-
-    if (!file.WriteKeyNT("STEP", fStep, ""))
-        return;
-
-    vector<char> buf;
-    buf.reserve(fStats.size()*sizeof(float));
-
-    char *src  = reinterpret_cast<char*>(fStats.data());
-    char *end  = reinterpret_cast<char*>(fStats.data()+1024*1440*6+3);
-    char *dest = buf.data();
-
-    while (src<end)
-    {
-        reverse_copy(src, src+sizeof(float), dest);
-        src  += sizeof(float);
-        dest += sizeof(float);
-    }
-
-    if (!file.AddRow())
-        return;
-
-    if (!file.WriteData(buf.data(), 1024*1440*sizeof(float)*6+3))
-        return;
-
-    ostringstream str;
-    str << "Wrote DRS calibration data (step=" << fStep << ") to '" << fFileName << "'";
-    Info(str.str());
-#endif
-}
-
-bool DataCalib::Close(RUN_TAIL *)
-{
-    if (fStep==0)
-    {
-        fOffset.assign(fSum.begin(), fSum.end());
-        fNumOffset = fNumEntries;
-
-        // Scale ADC data from 12bit to 2000mV
-        GetSampleStats(fStats.data()+3, 2000./4096);
-        reinterpret_cast<uint32_t*>(fStats.data())[0] = GetRunId();;
-    }
-    if (fStep==1)
-    {
-        fGain.assign(fSum.begin(), fSum.end());
-        fNumGain = fNumEntries*fNumOffset;
+        // 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
@@ -251,4 +190,102 @@
             fGain[i] *= 1024;
 
+        return true;
+    }
+    catch (const runtime_error &e)
+    {
+        msg.Error("Exception reading "+str+": "+e.what());
+        return false;
+    }
+}
+
+void DataCalib::WriteFits()
+{
+#ifdef HAVE_FITS
+    FitsFile file(fMsg);
+
+    file.AddColumn('I', "RunNumberBaseline");
+    file.AddColumn('I', "RunNumberGain");
+    file.AddColumn('I', "RunNumberTriggerOffset");
+    file.AddColumn('F', "BaselineMean",      1024*1440, "V");
+    file.AddColumn('F', "BaselineRms",       1024*1440, "V");
+    file.AddColumn('F', "GainMean",          1024*1440, "V");
+    file.AddColumn('F', "GainRms",           1024*1440, "V");
+    file.AddColumn('F', "TriggerOffsetMean", 1024*1440, "V");
+    file.AddColumn('F', "TriggerOffsetRms",  1024*1440, "V");
+
+    fFileName = FormFileName(GetRunId(), "drs.fits");
+
+    if (!file.OpenFile(fFileName))
+        return;
+
+    if (!file.OpenTable("DrsCalibration"))
+        return;
+
+    if (!file.WriteDefaultKeys("fadctrl"))
+        return;
+
+    if (!file.WriteKeyNT("STEP",     fStep, "") ||
+        !file.WriteKeyNT("ADCRANGE", 2000,             "Dynamic range of the ADC in mV") ||
+        !file.WriteKeyNT("DACRANGE", 2500,             "Dynamic range of the DAC in mV") ||
+        !file.WriteKeyNT("ADC",      12,               "Resolution of ADC in bits")
+        !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")
+       )
+        return;
+
+    vector<char> buf;
+    buf.reserve(fStats.size()*sizeof(float));
+
+    char *src  = reinterpret_cast<char*>(fStats.data());
+    char *end  = reinterpret_cast<char*>(fStats.data()+1024*1440*6+3);
+    char *dest = buf.data();
+
+    while (src<end)
+    {
+        reverse_copy(src, src+sizeof(float), dest);
+        src  += sizeof(float);
+        dest += sizeof(float);
+    }
+
+    if (!file.AddRow())
+        return;
+
+    if (!file.WriteData(buf.data(), 1024*1440*sizeof(float)*6+3))
+        return;
+
+    ostringstream str;
+    str << "Wrote DRS calibration data (step=" << fStep << ") to '" << fFileName << "'";
+    Info(str.str());
+#endif
+}
+
+bool DataCalib::Close(RUN_TAIL *)
+{
+    if (fStep==0)
+    {
+        fOffset.assign(fSum.begin(), fSum.end());
+        fNumOffset = fNumEntries;
+
+        // Scale ADC data from 12bit to 2000mV
+        GetSampleStats(fStats.data()+3, 2000./4096);
+        reinterpret_cast<uint32_t*>(fStats.data())[0] = GetRunId();;
+    }
+    if (fStep==1)
+    {
+        fGain.assign(fSum.begin(), fSum.end());
+        fNumGain = fNumEntries;
+
+        // DAC:  0..2.5V == 0..65535
+        // V-mV: 1000
+        //fNumGain *= 2500*50000;
+        //for (int i=0; i<1024*1440; i++)
+        //    fGain[i] *= 65536;
+        fNumGain *= 1953125;
+        for (int i=0; i<1024*1440; i++)
+            fGain[i] *= 1024;
+
         // Scale ADC data from 12bit to 2000mV
         GetSampleStats(fStats.data()+1024*1440*2+3, 2000./4096/fNumOffset);//0.5);
@@ -258,5 +295,5 @@
     {
         fTrgOff.assign(fSum.begin(), fSum.end());
-        fNumTrgOff = fNumEntries*fNumOffset;
+        fNumTrgOff = fNumEntries;
 
         // Scale ADC data from 12bit to 2000mV
