Index: trunk/FACT++/src/Description.cc
===================================================================
--- trunk/FACT++/src/Description.cc	(revision 16197)
+++ trunk/FACT++/src/Description.cc	(revision 16282)
@@ -93,5 +93,5 @@
 
     vector<Description> vec;
-    vec.push_back(Description(svc, d));
+    vec.emplace_back(svc, d);
 
     if (p==string::npos)
@@ -119,5 +119,5 @@
         const string name = hasunit ? buf.substr(0, p2) : buf;
 
-        vec.push_back(Description(name, comment, unit));
+        vec.emplace_back(name, comment, unit);
     }
 
Index: trunk/FACT++/src/DimState.h
===================================================================
--- trunk/FACT++/src/DimState.h	(revision 16197)
+++ trunk/FACT++/src/DimState.h	(revision 16282)
@@ -150,5 +150,5 @@
         {
             states = State::SplitStates(evt.GetString());
-            states.push_back(State(kOffline, "Offline"));
+            states.emplace_back(kOffline, "Offline");
 
             CallbackStates();
Index: trunk/FACT++/src/State.cc
===================================================================
--- trunk/FACT++/src/State.cc	(revision 16197)
+++ trunk/FACT++/src/State.cc	(revision 16282)
@@ -78,5 +78,5 @@
         const string comment = p2==string::npos ? "" : buf.substr(p2+1);
 
-        vec.push_back(State(index, name, comment));
+        vec.emplace_back(index, name, comment);
     }
 
Index: trunk/FACT++/src/StateMachineDimControl.cc
===================================================================
--- trunk/FACT++/src/StateMachineDimControl.cc	(revision 16197)
+++ trunk/FACT++/src/StateMachineDimControl.cc	(revision 16282)
@@ -476,5 +476,5 @@
             continue;
 
-        rc.push_back(State(it->first.second, it->second.first, it->second.second));
+        rc.emplace_back(it->first.second, it->second.first, it->second.second);
     }
 
Index: trunk/FACT++/src/StateMachineImp.cc
===================================================================
--- trunk/FACT++/src/StateMachineImp.cc	(revision 16197)
+++ trunk/FACT++/src/StateMachineImp.cc	(revision 16282)
@@ -166,5 +166,5 @@
 {
     const lock_guard<mutex> guard(fMutex);
-    fEventQueue.push_back(shared_ptr<Event>(cmd));
+    fEventQueue.emplace_back(cmd);
 }
 
Index: trunk/FACT++/src/datalogger.cc
===================================================================
--- trunk/FACT++/src/datalogger.cc	(revision 16197)
+++ trunk/FACT++/src/datalogger.cc	(revision 16282)
@@ -2004,16 +2004,16 @@
         vector<string> names;
         vector<string> dataTypes;
-        names.push_back("MEMBER_XTENSION");
-        dataTypes.push_back("8A");
-        names.push_back("MEMBER_URI_TYPE");
-        dataTypes.push_back("3A");
-        names.push_back("MEMBER_LOCATION");
+        names.emplace_back("MEMBER_XTENSION");
+        dataTypes.emplace_back("8A");
+        names.emplace_back("MEMBER_URI_TYPE");
+        dataTypes.emplace_back("3A");
+        names.emplace_back("MEMBER_LOCATION");
         dataTypes.push_back(pathTypeName.str());
-        names.push_back("MEMBER_NAME");
+        names.emplace_back("MEMBER_NAME");
         dataTypes.push_back(pathTypeName.str());
-        names.push_back("MEMBER_VERSION");
-        dataTypes.push_back("1J");
-        names.push_back("MEMBER_POSITION");
-        dataTypes.push_back("1J");
+        names.emplace_back("MEMBER_VERSION");
+        dataTypes.emplace_back("1J");
+        names.emplace_back("MEMBER_POSITION");
+        dataTypes.emplace_back("1J");
 
         groupTable = groupFile->addTable("GROUPING", numFilesToGroup, names, dataTypes);
Index: trunk/FACT++/src/feedback.cc
===================================================================
--- trunk/FACT++/src/feedback.cc	(revision 16197)
+++ trunk/FACT++/src/feedback.cc	(revision 16282)
@@ -37,4 +37,5 @@
         kFeedbackGlobal,
         kCurrents,
+        kCurrentsNew,
     };
 
@@ -94,5 +95,5 @@
     int HandleCameraTemp(const EventImp &evt)
     {
-        if (fControlType!=kTemp && fControlType!=kCurrents)
+        if (fControlType!=kTemp && fControlType!=kCurrents && fControlType!=kCurrentsNew)
             return GetCurrentState();
 
@@ -123,5 +124,242 @@
         fCursorTemp++;
 
-        return HandleCurrentControl();
+        return fControlType==kCurrentsNew ? HandleCurrentControlNew() : HandleCurrentControl();
+    }
+
+    int HandleCurrentControlNew()
+    {
+        if (GetCurrentState()==Feedback::State::kCalibrating && fBiasOffset>fTempOffset-1.2)
+        {
+            fCursorTemp = 0;
+
+            ostringstream msg;
+            msg << " (applied calibration offset " << fBiasOffset << "V exceeds temperature correction " << fTempOffset << "V - 1.2V.";
+            Warn("Trying to calibrate above G-APD breakdown volatge!");
+            Warn(msg);
+            return GetCurrentState();
+        }
+
+        double avg[2] = {   0,   0 };
+        double min[2] = {  90,  90 };
+        double max[2] = { -90, -90 };
+        int    num[2] = {   0,   0 };
+
+        vector<double> med[2];
+        med[0].resize(416);
+        med[1].resize(416);
+
+        const float *Ravg = fCalibration.data()+BIAS::kNumChannels*2; // Measured resistance
+
+        vector<float> vec(2*BIAS::kNumChannels+2);
+
+        vec[BIAS::kNumChannels*2]   = fTempOffset;
+        vec[BIAS::kNumChannels*2+1] = fBiasOffset;
+
+        float *Uoff = vec.data()+BIAS::kNumChannels;
+
+        if (GetCurrentState()==Feedback::State::kCalibrating)
+            for (int i=0; i<BIAS::kNumChannels; i++)
+                Uoff[i] = fBiasOffset;
+        else
+            for (int i=0; i<BIAS::kNumChannels; i++)
+                Uoff[i] = fTempOffset+fBiasOffset;
+
+        if (fControlType==kCurrentsNew)
+        {
+            // Would be a devision by zero. We need informations first.
+            if (fCursorCur==0)
+                return GetCurrentState();
+
+            for (int i=0; i<BIAS::kNumChannels; i++)
+            {
+                const PixelMapEntry &hv = fMap.hv(i);
+                if (!hv)
+                    continue;
+
+                // Nominal breakdown voltage (includes overvoltage already)
+                double Ubd = fVoltGapd[i];
+
+                // Nominal breakdown voltage excluding overvoltage of 1.1V
+                Ubd -= 1.1;
+
+                // Correct breakdown voltage for temperature dependence
+                Ubd += fTempOffset;
+
+                // Number of G-APDs in this patch
+                const int N = hv.group() ? 5 : 4;
+
+                // 100 Ohm measurement resistor for current measurement
+                const double R2 = 100;
+
+                // Serial resistors (one 1kOhm at the output of the bias crate, one 1kOhm in the camera)
+                const double R4 = 2000;
+
+                // Serial resistor of the individual G-APDs
+                double R5 = 3900/N;
+
+                // This is assuming that the broken pixels have a 390 Ohm instead of 3900 Ohm serial resistor
+                if (i==66)                 // Pixel 830(66)
+                    R5 = 300;              // 2400 = 1/(3/3900 + 1/390)
+                if (i==191 || i==193)      // Pixel 583(191) / Pixel 1401(193)
+                    R5 = 390/1.4;          // 379 = 1/(4/3900 + 1/390)
+
+                // Total resistance of branch with diode
+                const double R3 = R4+R5;
+
+                // Measured calibration resistor
+                const double R1 = Ravg[i] - R2;
+
+                // Voltage output of bias crate
+                const double Uout = fBiasVolt[i];
+
+                // Average current measured for this channel
+                const double Imes = double(fCurrentsAvg[i])/fCursorCur * (5000/4096.); // [uA]
+
+                // Voltage drop at measurement resistor R2 is define
+                // bythe measured current and the resistor
+                const double U2 = R2*Imes;
+
+                // The voltage seen by the calibration resistor R1 is defined by the
+                // bias crate output voltage minus the drop at the measurement resistor R2
+                const double U1 = Uout - U2;
+
+                // The current through the resistor R1 is defined
+                // by the applied voltage and the resistor
+                const double I1 = U1/R1;
+
+                // The current through the diode branch is the measured current
+                // minus the current through the calibration resistor R1
+                const double I3 = Imes - I1;
+
+                // The voltage drop in the diode branch (without the diode) is defined by the
+                // resistor and the current. It is 0 below the breakdown voltage of the G-APD
+                // is reached at the G-APD. This is the case when the output voltage minus
+                // the voltage drop at the calibration resistor reaches the breakdown voltage.
+                const double U3 = Uout-U2<Ubd ? 0 : R3*I3;
+
+                // Voltage drop at measurement resistor R2 and
+                // the total serial resistor R3 in the diode branch
+                const double Udrp = U2 + U3;
+
+                // Voltage finally at each G-APD (bias crate output voltage minus voltage drop)
+                const double Uapd = Uout - Udrp;
+
+                // The over-voltage seen by the G-APD (the voltage above the breakdown voltage) is
+                const double Uov = Uapd<Ubd ? 0 : Uapd - Ubd;
+
+                // The current through one G-APD is the sum divided by the number of G-APDs
+                // (assuming identical serial resistors)
+                double Iapd = I3/N;
+
+                // This is assuming that the broken pixels have a 390 Ohm instead of 3900 Ohm serial resistor
+                // In this and the previosu case we neglect the resistance of the G-APDs, but we can make an
+                // assumption: The differential resistance depends more on the NSB than on the PDE,
+                // thus it is at least comparable for all G-APDs in the patch. In addition, although the
+                // G-APD with the 390Ohm serial resistor has the wrong voltage applied, this does not
+                // significantly influences the ohmic resistor or the G-APD because the differential
+                // resistor is large enough that the increase of the overvoltage does not dramatically
+                // increase the current flow as compared to the total current flow.
+                if (i==66)
+                    Iapd *= 1.3;
+                if (i==191 || i==193)
+                    Iapd *= 1.4;
+
+                // If the G-APD voltage is above the breakdown voltage we have the current through the
+                // G-APD and the over-voltage applied to the G-APD to calculate its differential resistor.
+                if (Uapd>Ubd)
+                {
+                    // The differential resistance of the G-APD, i.e. the dependence of the
+                    // current above the breakdown voltage, is given by
+                    const double Rapd = Uov/Iapd;
+
+                    // This allows us to estimate the current Iov at the overvoltage we want to apply
+                    const double Iov = (1.1+fBiasOffset)/Rapd;
+
+                    // This gives us an ohmic resistance Rov of the G-APD at the set-point
+                    const double Rest = (Ubd+1.1+fBiasOffset)/Iov;
+
+                    // This lets us estimate the total resistance Rtot of the circuit at the set-point
+                    const double R3b  = R4 + (R5+Rest)/N;
+                    const double Rtot = R2 + 1/(1/R1 + 1/R3b);
+
+                    // From this we can estimate the output voltage we need to get the
+                    // over-voltage at the G-APD as anticipated
+                    const double r    = 1 + R3/R1 - (R2 + R3 + R3*R2/R1)/Rtot;
+                    const double Uset = (Ubd+1.1+fBiasOffset)/r;
+
+                    Uoff[i] = Uset - fVoltGapd[i];
+                }
+
+                 // Calculate statistics only for channels with a valid calibration
+                 if (Uov>0)
+                 {
+                     const int g = hv.group();
+
+                     med[g][num[g]] = Uov;
+                     avg[g] += Uov;
+                     num[g]++;
+
+                     if (Uov<min[g])
+                         min[g] = Uov;
+                     if (Uov>max[g])
+                         max[g] = Uov;
+                 }
+            }
+
+            sort(med[0].begin(), med[0].begin()+num[0]);
+            sort(med[1].begin(), med[1].begin()+num[1]);
+
+            fCurrentsAvg.assign(BIAS::kNumChannels, 0);
+            fCursorCur = 0;
+        }
+
+        fDimDeviation.setQuality(fControlType);
+        fDimDeviation.Update(vec);
+
+        // Warning: Here it is assumed that the ramp up and down is done properly
+        // within the time between two new temperatures and that the calibration
+        // is finished within that time.
+        if (GetCurrentState()!=Feedback::State::kCalibrating ||
+            fDimBias.state()!=BIAS::State::kVoltageOff ||
+            fCursorTemp!=1 || !fOutputEnabled)
+        {
+            if (!fOutputEnabled || fDimBias.state()!=BIAS::State::kVoltageOn)
+                return GetCurrentState();
+
+            // Trigger calibration
+            if (GetCurrentState()==Feedback::State::kCalibrating && fCursorTemp==2)
+            {
+                DimClient::sendCommandNB("BIAS_CONTROL/REQUEST_STATUS", NULL, 0);
+                return GetCurrentState();
+            }
+        }
+
+        ostringstream msg;
+        msg << setprecision(4) << "Sending new absolute offset (" << fAppliedOffset << "V+" << (num[0]+num[1]>0?(avg[0]+avg[1])/(num[0]+num[1]):0) << "V) to biasctrl.";
+        Info(msg);
+
+        if (fControlType==kCurrents && num[0]>0 && num[1]>0)
+        {
+            msg.str("");
+            msg << "   Avg0=" << setw(7) << avg[0]/num[0]    << "  |  Avg1=" << setw(7) << avg[1]/num[1];
+            Debug(msg);
+
+            msg.str("");
+            msg << "   Med0=" << setw(7) << med[0][num[0]/2] << "  |  Med1=" << setw(7) << med[1][num[1]/2];
+            Debug(msg);
+
+            msg.str("");
+            msg << "   Min0=" << setw(7) << min[0]           << "  |  Min1=" << setw(7) << min[1];
+            Debug(msg);
+
+            msg.str("");
+            msg << "   Max0=" << setw(7) << max[0]           << "  |  Max1=" << setw(7) << max[1];
+            Debug(msg);
+        }
+
+        DimClient::sendCommandNB("BIAS_CONTROL/SET_ALL_CHANNELS_OFFSET",
+                                 vec.data()+BIAS::kNumChannels, BIAS::kNumChannels*sizeof(float));
+
+        return GetCurrentState();
     }
 
@@ -727,5 +965,5 @@
     void HandleCalibrateCurrents(const EventImp &evt)
     {
-        if (fBiasVolt.size()==0 || fCalibration.size()==0 || evt.GetSize()<416*sizeof(int16_t))
+        if (fBiasVolt.empty() || fCalibration.empty() || evt.GetSize()<416*sizeof(int16_t))
             return;
 
@@ -806,5 +1044,5 @@
             HandleCalibration(evt);
 
-        if (fControlType==kFeedbackGlobal || fControlType==kCurrents)
+        if (fControlType==kFeedbackGlobal || fControlType==kCurrents || fControlType==kCurrentsNew)
             AverageCurrents(evt);
 
@@ -875,5 +1113,5 @@
     int PrintCalibration()
     {
-        if (fCalibration.size()==0)
+        if (fCalibration.empty())
         {
             Out() << "No calibration performed so far." << endl;
@@ -953,5 +1191,5 @@
         fOutputEnabled = evt.GetBool();
 
-        if (fControlType==kCurrents)
+        if (fControlType==kCurrents || fControlType==kCurrentsNew)
             if (fCursorTemp>1)
                 fCursorTemp = 1;
@@ -1043,5 +1281,5 @@
             return kSM_FatalError;
 
-        if (fCalibration.size()==0)
+        if (fCalibration.empty())
         {
             Warn("Current control needs a bias crate calibration first... command ignored.");
@@ -1063,4 +1301,29 @@
     }
 
+    int StartNewCurrentCtrl(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "StartNewCurrentCtrl", 4))
+            return kSM_FatalError;
+
+        if (fCalibration.empty())
+        {
+            Warn("Current control needs a bias crate calibration first... command ignored.");
+            return GetCurrentState();
+        }
+
+        WarnState(true, false);
+
+        fBiasOffset = evt.GetFloat();
+        fTempOffset = -3;
+        ResetData(0);
+        fControlType = kCurrentsNew;
+
+        ostringstream out;
+        out << "Starting new current/temp feedback with an offset of " << fBiasOffset << "V";
+        Message(out);
+
+        return GetCurrentState();
+    }
+
     int StopFeedback()
     {
@@ -1130,5 +1393,5 @@
         }
 
-        if (fVoltGapd.size()==0)
+        if (fVoltGapd.empty())
         {
             Error("No G-APD reference voltages received yet (BIAS_CONTROL/NOMINAL).");
@@ -1248,5 +1511,5 @@
                 return fOutputEnabled ? Feedback::State::kTempCtrlRunning : Feedback::State::kTempCtrlIdle;
             }
-            if (fControlType==kCurrents)
+            if (fControlType==kCurrents || fControlType==kCurrentsNew)
             {
                 static Time past;
Index: trunk/FACT++/src/makedata.cc
===================================================================
--- trunk/FACT++/src/makedata.cc	(revision 16197)
+++ trunk/FACT++/src/makedata.cc	(revision 16282)
@@ -141,5 +141,5 @@
         const double disk = ln_get_lunar_disk(jd+h);
 
-        fMoonCoords.push_back(make_pair(moon, disk));
+        fMoonCoords.emplace_back(moon, disk);
     }
 
Index: trunk/FACT++/src/makeplots.cc
===================================================================
--- trunk/FACT++/src/makeplots.cc	(revision 16197)
+++ trunk/FACT++/src/makeplots.cc	(revision 16282)
@@ -157,5 +157,5 @@
         const double disk = Nova::GetLunarDisk(jd+h);
 
-        fMoonCoords.push_back(make_pair(moon, disk));
+        fMoonCoords.emplace_back(moon, disk);
     }
 
Index: trunk/FACT++/src/ratecontrol.cc
===================================================================
--- trunk/FACT++/src/ratecontrol.cc	(revision 16197)
+++ trunk/FACT++/src/ratecontrol.cc	(revision 16282)
@@ -410,7 +410,7 @@
 
         // Keep all median currents of the past 10 seconds
-        fCurrentsMed.push_back(make_pair(time, med));
-        fCurrentsDev.push_back(make_pair(time, dev));
-        fCurrentsVec.push_back(make_pair(time, vector<float>(cur, cur+320)));
+        fCurrentsMed.emplace_back(time, med);
+        fCurrentsDev.emplace_back(time, dev);
+        fCurrentsVec.emplace_back(time, vector<float>(cur, cur+320));
         while (!fCurrentsMed.empty())
         {
Index: trunk/FACT++/src/smartfact.cc
===================================================================
--- trunk/FACT++/src/smartfact.cc	(revision 16197)
+++ trunk/FACT++/src/smartfact.cc	(revision 16282)
@@ -368,5 +368,5 @@
                 pop_front();
 
-            push_back(EventElement(t, s));
+            emplace_back(t, s);
         }
 
@@ -1912,5 +1912,5 @@
             const double disk = Nova::GetLunarDisk(jd+h);
 
-            fMoonCoords.push_back(make_pair(moon, disk));
+            fMoonCoords.emplace_back(moon, disk);
         }
     }
