diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp
index cbd150631e3c0902108d43bba3996fe34660187c..c4bd9be8692f416807d1c29074c28d08eaffa5c7 100644
--- a/Fltk/graphicWindow.cpp
+++ b/Fltk/graphicWindow.cpp
@@ -2098,6 +2098,14 @@ static std::vector<std::string> getInfoStrings(MElement *ele)
     sstream << " SICN range: " << sICNMin << " " << sICNMax;
     info.push_back(sstream.str());
   }
+  {
+    std::ostringstream sstream;
+    sstream.precision(12);
+    double sIGEMin, sIGEMax;
+    ele->signedInvGradErrorRange(sIGEMin, sIGEMax);
+    sstream << " SIGE range: " << sIGEMin << " " << sIGEMax;
+    info.push_back(sstream.str());
+  }
   {
     std::ostringstream sstream;
     sstream.precision(12);
diff --git a/Fltk/optionWindow.cpp b/Fltk/optionWindow.cpp
index 5f30aa793af0bef8549ecc26b5243e33bacfb214..efa878f7530b20ca034470f7124c38f521b61a49 100644
--- a/Fltk/optionWindow.cpp
+++ b/Fltk/optionWindow.cpp
@@ -2518,6 +2518,7 @@ optionWindow::optionWindow(int deltaFontSize)
 
       static Fl_Menu_Item menu_quality_type[] = {
         {"SICN", 0, 0, 0},
+        {"SIGE", 0, 0, 0},
         {"Gamma", 0, 0, 0},
         {"Rho", 0, 0, 0},
         {"Disto", 0, 0, 0},
diff --git a/Fltk/statisticsWindow.cpp b/Fltk/statisticsWindow.cpp
index 7f5e88acd600976d58dc231997b23040a1749989..ed6919a4f6ea7ecf17648450436ab62d2d4064f9 100644
--- a/Fltk/statisticsWindow.cpp
+++ b/Fltk/statisticsWindow.cpp
@@ -18,7 +18,10 @@
 #include "OS.h"
 #include "Field.h"
 
-enum QM_HISTO {QMH_SICN_XY, QMH_SICN_3D, QMH_GAMMA_XY, QMH_GAMMA_3D, QMH_RHO_XY, QMH_RHO_3D};
+enum QM_HISTO {QMH_SICN_XY, QMH_SICN_3D,
+               QMH_GAMMA_XY, QMH_GAMMA_3D,
+               QMH_RHO_XY, QMH_RHO_3D,
+               QMH_SIGE_XY, QMH_SIGE_3D};
 
 void statistics_cb(Fl_Widget *w, void *data)
 {
@@ -57,6 +60,13 @@ static void statistics_histogram_cb(Fl_Widget *w, void *data)
     }
     new PView("Rho", "# Elements", x, y);
   }
+  else if (qmh == QMH_SIGE_XY) {
+    for(int i = 0; i < 100; i++){
+      x.push_back((double)(2*i-99) / 99);
+      y.push_back(FlGui::instance()->stats->quality[3][i]);
+    }
+    new PView("SIGE", "# Elements", x, y);
+  }
   else {
     std::vector<GEntity*> entities_;
     GModel::current()->getEntities(entities_);
@@ -71,11 +81,14 @@ static void statistics_histogram_cb(Fl_Widget *w, void *data)
           d[e->getNum()].push_back(e->gammaShapeMeasure());
         else if (qmh == QMH_RHO_3D)
           d[e->getNum()].push_back(e->rhoShapeMeasure());
+        else if (qmh == QMH_SIGE_3D)
+          d[e->getNum()].push_back(e->minSIGEShapeMeasure());
       }
     }
     std::string name = (qmh == QMH_SICN_3D) ? "SICN" :
                        (qmh == QMH_GAMMA_3D) ? "Gamma" :
-                       (qmh == QMH_RHO_3D) ? "Rho" : "";
+                       (qmh == QMH_RHO_3D) ? "Rho" :
+                       (qmh == QMH_SIGE_3D) ? "SIGE" : "";
     new PView(name, "ElementData", GModel::current(), d);
   }
 
@@ -89,7 +102,7 @@ statisticsWindow::statisticsWindow(int deltaFontSize)
 
   int num = 0;
   int width = 26 * FL_NORMAL_SIZE;
-  int height = 5 * WB + 18 * BH;
+  int height = 5 * WB + 19 * BH;
 
   win = new paletteWindow
     (width, height, CTX::instance()->nonModalWindows ? true : false, "Statistics");
@@ -126,12 +139,14 @@ statisticsWindow::statisticsWindow(int deltaFontSize)
 
       value[num] = new Fl_Output(2 * WB, 2 * WB + 14 * BH, IW, BH, "SICN");
       value[num]->tooltip("~ signed inverse condition number"); num++;
-      value[num] = new Fl_Output(2 * WB, 2 * WB + 15 * BH, IW, BH, "Gamma");
+      value[num] = new Fl_Output(2 * WB, 2 * WB + 15 * BH, IW, BH, "SIGE");
+      value[num]->tooltip("~ signed inverse error on gradient FE solution"); num++;
+      value[num] = new Fl_Output(2 * WB, 2 * WB + 16 * BH, IW, BH, "Gamma");
       value[num]->tooltip("~ inscribed_radius / circumscribed_radius (simplices)"); num++;
-      value[num] = new Fl_Output(2 * WB, 2 * WB + 16 * BH, IW, BH, "Rho");
+      value[num] = new Fl_Output(2 * WB, 2 * WB + 17 * BH, IW, BH, "Rho");
       value[num]->tooltip("~ min_edge_length / max_edge_length"); num++;
 
-      for(int i = 0; i < 3; i++){
+      for(int i = 0; i < 4; i++){
         int ww = 3 * FL_NORMAL_SIZE;
         new Fl_Box
           (FL_NO_BOX, width - 3 * ww - 2 * WB, 2 * WB + (14 + i) * BH, ww, BH, "Plot");
@@ -141,13 +156,16 @@ statisticsWindow::statisticsWindow(int deltaFontSize)
           (width - ww - 2 * WB, 2 * WB + (14 + i) * BH, ww, BH, "3D");
       }
       static const QM_HISTO qmh0 = QMH_SICN_XY, qmh1 = QMH_SICN_3D, qmh2 = QMH_GAMMA_XY,
-                            qmh3 = QMH_GAMMA_3D, qmh4 = QMH_RHO_XY, qmh5 = QMH_RHO_3D;
+                            qmh3 = QMH_GAMMA_3D, qmh4 = QMH_RHO_XY, qmh5 = QMH_RHO_3D,
+                            qmh6 = QMH_SIGE_XY, qmh7 = QMH_SIGE_3D;
       butt[0]->callback(statistics_histogram_cb, (void*) &qmh0);
       butt[1]->callback(statistics_histogram_cb, (void*) &qmh1);
       butt[2]->callback(statistics_histogram_cb, (void*) &qmh2);
       butt[3]->callback(statistics_histogram_cb, (void*) &qmh3);
       butt[4]->callback(statistics_histogram_cb, (void*) &qmh4);
       butt[5]->callback(statistics_histogram_cb, (void*) &qmh5);
+      butt[6]->callback(statistics_histogram_cb, (void*) &qmh6);
+      butt[7]->callback(statistics_histogram_cb, (void*) &qmh7);
 
       group[1]->end();
     }
@@ -225,7 +243,10 @@ void statisticsWindow::compute(bool elementQuality)
   sprintf(label[num], "%g", s[16]); value[num]->value(label[num]); num++;
 
   if(!elementQuality){
-    for(int i = 0; i < 6; i += 2) butt[i]->deactivate();
+    for(int i = 0; i < 8; i += 2) butt[i]->deactivate();
+    sprintf(label[num], "Press Update");
+    value[num]->deactivate();
+    value[num]->value(label[num]); num++;
     sprintf(label[num], "Press Update");
     value[num]->deactivate();
     value[num]->value(label[num]); num++;
@@ -237,7 +258,7 @@ void statisticsWindow::compute(bool elementQuality)
     value[num]->value(label[num]); num++;
   }
   else{
-    for(int i = 0; i < 6; i += 2) butt[i]->activate();
+    for(int i = 0; i < 8; i += 2) butt[i]->activate();
     sprintf(label[num], "%.4g (%.4g->%.4g)", s[18], s[19], s[20]);
     value[num]->activate();
     value[num]->value(label[num]); num++;
diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp
index 880936ba498ff6a16f22b51edfdb74270f59419e..f863409c310229baed5b517f2ec23c8290efebe0 100644
--- a/Geo/MElement.cpp
+++ b/Geo/MElement.cpp
@@ -334,6 +334,14 @@ void MElement::signedInvCondNumRange(double &iCNMin, double &iCNMax, GEntity *ge
 #endif
 }
 
+void MElement::signedInvGradErrorRange(double &minSIGE, double &maxSIGE,
+                                       GEntity *ge)
+{
+  minSIGE = jacobianBasedQuality::minSampledICNMeasure(this, getPolynomialOrder());
+  maxSIGE = 1;
+  return;
+}
+
 void MElement::getNode(int num, double &u, double &v, double &w) const
 {
   // only for MElements that don't have a lookup table for this
diff --git a/Geo/MElement.h b/Geo/MElement.h
index 7fa7470a99a63229ff20e7c51b50bf684b5f1cab..9c1318fed98deb755d3a9d8f595800ee24411bcb 100644
--- a/Geo/MElement.h
+++ b/Geo/MElement.h
@@ -202,18 +202,24 @@ class MElement
   virtual double rhoShapeMeasure();
   virtual double gammaShapeMeasure(){ return 0.; }
   virtual double etaShapeMeasure(){ return 0.; }
-  double distoShapeMeasure()
-  {
-    double jmin, jmax;
-    scaledJacRange(jmin, jmax);
-    return jmin;
-  }
   double minSICNShapeMeasure()
   {
     double sICNMin, sICNMax;
     signedInvCondNumRange(sICNMin, sICNMax);
     return sICNMin;
   }
+  double minSIGEShapeMeasure()
+  {
+    double minSIGE, maxSIGE;
+    signedInvGradErrorRange(minSIGE, maxSIGE);
+    return minSIGE;
+  }
+  double distoShapeMeasure()
+  {
+    double jmin, jmax;
+    scaledJacRange(jmin, jmax);
+    return jmin;
+  }
   double minIsotropyMeasure(bool knownValid = false, bool reversedOk = false);
   double minScaledJacobian(bool knownValid = false, bool reversedOk = false);
   double specialQuality();
@@ -222,6 +228,7 @@ class MElement
   virtual void scaledJacRange(double &jmin, double &jmax, GEntity *ge = 0) const;
   virtual void idealJacRange(double &jmin, double &jmax, GEntity *ge = 0);
   virtual void signedInvCondNumRange(double &iCNMin, double &iCNMax, GEntity *ge = 0);
+  virtual void signedInvGradErrorRange(double &minSIGE, double &maxSIGE, GEntity *ge = 0);
 
   // get the radius of the inscribed circle/sphere if it exists,
   // otherwise get the minimum radius of all the circles/spheres