diff --git a/Plugin/AnalyseCurvedMesh.cpp b/Plugin/AnalyseCurvedMesh.cpp
index e389beecb5b163343eb8db26238b4076d32839cf..2e6a1b0f9d656c5bf54397353f61643b176654fc 100644
--- a/Plugin/AnalyseCurvedMesh.cpp
+++ b/Plugin/AnalyseCurvedMesh.cpp
@@ -13,11 +13,15 @@
 
 
 StringXNumber JacobianOptions_Number[] = {
-  {GMSH_FULLRC, "Method", NULL, 1},
-  {GMSH_FULLRC, "MaxDepth", NULL, 5}
+  {GMSH_FULLRC, "Dim", NULL, -1},
+  {GMSH_FULLRC, "Analysis", NULL, 1},
+  {GMSH_FULLRC, "Effect", NULL, 6},
+  {GMSH_FULLRC, "MaxDepth", NULL, 10},
+  {GMSH_FULLRC, "JacBreak", NULL, .0},
+  {GMSH_FULLRC, "BezBreak", NULL, .0},
+  {GMSH_FULLRC, "Tolerance", NULL, 1e-5}
 };
 
-
 extern "C"
 {
   GMSH_Plugin *GMSH_RegisterAnalyseCurvedMeshPlugin()
@@ -37,28 +41,40 @@ StringXNumber *GMSH_AnalyseCurvedMeshPlugin::getOption(int iopt)
 
 std::string GMSH_AnalyseCurvedMeshPlugin::getHelp() const
 {
-  return "Plugin(AnalyseCurvedMesh) check the jacobian of all elements of the greater dimension. "
-    "Elements for which we are absolutely certain that they are good (positive jacobian) are ignored. "
-    "Others are wrong or suppose to be wrong.\n\n"
-    "Plugin(AnalyseCurvedMesh) write in the console which elements are wrong. "
-    "(if labels of analysed type of elements are set visible, only wrong elements will be visible)\n\n"
-    "method = 1 or 2\n"
-    "maxDepth >= 0 (> 1 is better)\n\n"
-    "maxDepth = 0 : only sampling of the jacobian\n"
-    "maxDepth = 1 : also calculate control points\n"
-    "maxDepth = 2+ : also decompose control points\n";
+  return "Plugin(AnalyseCurvedMesh) check the jacobian of all elements of dimension 'Dim' or "
+    "the greater model dimension if 'Dim' is either <0 or >3.\n\n "
+    //"Elements for which we are absolutely certain that they are good (positive jacobian) are ignored. "
+    //"Others are wrong or suppose to be wrong.\n\n"
+    //"Plugin(AnalyseCurvedMesh) write in the console which elements are wrong. "
+    //"(if labels of analysed type of elements are set visible, only wrong elements will be visible)\n\n"
+    "Analysis : 0 do nothing\n"
+    "          +1 find invalid elements (*)\n"
+    "          +2 compute min and max of all elements and print some statistics\n\n"
+    "Effect (for *) : 0 do nothing\n"
+    "                +1 print a list of invalid elements\n"
+    "                +2 print some statistics\n"
+    "                +4 hide valid elements (for GUI)\n\n"
+    "MaxDepth = {0,1,...}\n"
+    "         0 : only sample the jacobian\n"
+    "         1 : compute Bezier coefficients\n"
+    "        2+ : execute a maximum of 1+ subdivision(s)\n\n"
+    "JacBreak = [0,1[ : if a value of the jacobian <= 'JacBreak' is found, "
+    "the element is said to be invalid\n\n"
+    "BezBreak = [0,JacBreak[ : if all Bezier coefficients are > 'BezBreak', "
+    "the element is said to be valid\n\n"
+    "Tolerance = R+ , << 1 : tolerance (relatively to J_avg.) used during the computation of min and max";
 }
 
 // Miscellaneous method
-int max(const std::vector<int> &vec)
+/*int max(const std::vector<int> &vec)
 {
   int max = vec[0];
   for (unsigned int i = 1; i < vec.size(); i++)
     if (vec[i] > max) max = vec[i];
   return max;
-}
+}*/
 
-static double computeDeterminant(MElement *el, double jac[3][3])
+/*static double computeDeterminant(MElement *el, double jac[3][3])
 {
   switch (el->getDim()) {
   case 0:
@@ -93,9 +109,9 @@ double getJacobian(double gsf[][3], double jac[3][3], MElement *el)
   }
 
   return computeDeterminant(el, jac);
-}
+}*/
 
-void setJacobian(MElement *el, const JacobianBasis *jfs, fullVector<double> &jacobian)
+static void setJacobian(MElement *el, const JacobianBasis *jfs, fullVector<double> &jacobian)
 {
   int numVertices = el->getNumVertices();
   fullVector<double> nodesX(numVertices);
@@ -103,88 +119,84 @@ void setJacobian(MElement *el, const JacobianBasis *jfs, fullVector<double> &jac
   fullVector<double> nodesZ;
   fullVector<double> interm1;
   fullVector<double> interm2;
-
+  
   switch (el->getDim()) {
-
+    
     case 1 :
       for (int i = 0; i < numVertices; i++) {
         nodesX(i) = el->getVertex(i)->x();
       }
       jfs->gradShapeMatX.mult(nodesX, jacobian);
       break;
-
-
+    
     case 2 :
-
       nodesY.resize(numVertices);
       interm1.resize(jacobian.size());
       interm2.resize(jacobian.size());
-
+      
       for (int i = 0; i < numVertices; i++) {
         nodesX(i) = el->getVertex(i)->x();
         nodesY(i) = el->getVertex(i)->y();
       }
-
+      
       jfs->gradShapeMatX.mult(nodesX, jacobian);
       jfs->gradShapeMatY.mult(nodesY, interm2);
       jacobian.multTByT(interm2);
-
+      
       jfs->gradShapeMatY.mult(nodesX, interm1);
       jfs->gradShapeMatX.mult(nodesY, interm2);
       interm1.multTByT(interm2);
-
+      
       jacobian.axpy(interm1, -1);
       break;
-
-
+    
     case 3 :
-
       nodesY.resize(numVertices);
       nodesZ.resize(numVertices);
       interm1.resize(jacobian.size());
       interm2.resize(jacobian.size());
-
+      
       for (int i = 0; i < numVertices; i++) {
         nodesX(i) = el->getVertex(i)->x();
         nodesY(i) = el->getVertex(i)->y();
         nodesZ(i) = el->getVertex(i)->z();
       }
-
+      
       jfs->gradShapeMatX.mult(nodesX, jacobian);
       jfs->gradShapeMatY.mult(nodesY, interm2);
       jacobian.multTByT(interm2);
       jfs->gradShapeMatZ.mult(nodesZ, interm2);
       jacobian.multTByT(interm2);
-
+      
       jfs->gradShapeMatX.mult(nodesY, interm1);
       jfs->gradShapeMatY.mult(nodesZ, interm2);
       interm1.multTByT(interm2);
       jfs->gradShapeMatZ.mult(nodesX, interm2);
       interm1.multTByT(interm2);
       jacobian.axpy(interm1, 1);
-
+      
       jfs->gradShapeMatX.mult(nodesZ, interm1);
       jfs->gradShapeMatY.mult(nodesX, interm2);
       interm1.multTByT(interm2);
       jfs->gradShapeMatZ.mult(nodesY, interm2);
       interm1.multTByT(interm2);
       jacobian.axpy(interm1, 1);
-
-
+      
+      
       jfs->gradShapeMatX.mult(nodesY, interm1);
       jfs->gradShapeMatY.mult(nodesX, interm2);
       interm1.multTByT(interm2);
       jfs->gradShapeMatZ.mult(nodesZ, interm2);
       interm1.multTByT(interm2);
       jacobian.axpy(interm1, -1);
-
+      
       jfs->gradShapeMatX.mult(nodesZ, interm1);
       jfs->gradShapeMatY.mult(nodesY, interm2);
       interm1.multTByT(interm2);
       jfs->gradShapeMatZ.mult(nodesX, interm2);
       interm1.multTByT(interm2);
       jacobian.axpy(interm1, -1);
-
+      
       jfs->gradShapeMatX.mult(nodesX, interm1);
       jfs->gradShapeMatY.mult(nodesZ, interm2);
       interm1.multTByT(interm2);
@@ -195,7 +207,7 @@ void setJacobian(MElement *el, const JacobianBasis *jfs, fullVector<double> &jac
 }
 
 
-void setJacobian(MElement *const *el, const JacobianBasis *jfs, fullMatrix<double> &jacobian)
+/*void setJacobian(MElement *const *el, const JacobianBasis *jfs, fullMatrix<double> &jacobian)
 {
   int numEl = jacobian.size2();
   int numVertices = el[0]->getNumVertices();
@@ -204,9 +216,9 @@ void setJacobian(MElement *const *el, const JacobianBasis *jfs, fullMatrix<doubl
   fullMatrix<double> nodesZ;
   fullMatrix<double> interm1;
   fullMatrix<double> interm2;
-
+  
   switch (el[0]->getDim()) {
-
+    
     case 1 :
       for (int j = 0; j < numEl; j++) {
         for (int i = 0; i < numVertices; i++) {
@@ -215,10 +227,8 @@ void setJacobian(MElement *const *el, const JacobianBasis *jfs, fullMatrix<doubl
       }
       jfs->gradShapeMatX.mult(nodesX, jacobian);
       break;
-
-
+    
     case 2 :
-
       nodesY.resize(numVertices,numEl);
       interm1.resize(jacobian.size1(),jacobian.size2());
       interm2.resize(jacobian.size1(),jacobian.size2());
@@ -299,18 +309,38 @@ void setJacobian(MElement *const *el, const JacobianBasis *jfs, fullMatrix<doubl
       interm1.multTByT(interm2);
       jacobian.add(interm1, -1);
   }
-}
+}*/
 
 
 // Execution
 PView *GMSH_AnalyseCurvedMeshPlugin::execute(PView *v)
 {
-  Msg::Info("AnalyseCurvedMeshPlugin : Starting analyse.");
+  _m = GModel::current();
+  _dim = (int) JacobianOptions_Number[0].def;
+  if (_dim < 0 || _dim > 3)
+    _dim = _m->getDim();
+  int analysis = (int) JacobianOptions_Number[1].def % 4;
+  int toDo = (int) JacobianOptions_Number[2].def % 8;
+  _maxDepth = (int) JacobianOptions_Number[3].def;
+  _jacBreak = (double) JacobianOptions_Number[4].def;
+  _bezBreak = (double) JacobianOptions_Number[5].def;
+  _tol = (double) JacobianOptions_Number[6].def;
+  
+  if (analysis % 2) {
+    checkValidity(toDo);
+  }
+  if (analysis / 2) {
+    computeMinMax();
+  }
+}
+  
+{
+  Msg::Info("AnalyseCurvedMeshPlugin : Starting analysis.");
   int numBadEl = 0;
   int numUncertain = 0;
   int numAnalysedEl = 0;
   std::vector<int> tag;
-  int method = (int)JacobianOptions_Number[0].def;
+  int method = (int)JacobianOptions_Number[0].def % 4;
   int maxDepth = (int)JacobianOptions_Number[1].def;
 
   if (method < 1 || method > 2) {
@@ -443,6 +473,213 @@ PView *GMSH_AnalyseCurvedMeshPlugin::execute(PView *v)
   return 0;
 }
 
+
+void GMSH_AnalyseCurvedMeshPlugin::checkValidity(int toDo)
+{
+  std::vector<MElement*> invalids;
+  _numAnalysedEl = 0;
+  _numInvalid = 0;
+  _numValid = 0;
+  _numUncertain = 0;
+  
+  switch (_dim) {
+    case 3 :
+      for(GModel::riter it = _m->firstRegion(); it != _m->lastRegion(); it++) {
+        GRegion *r = *it;
+        unsigned int numType[5] = {0, 0, 0, 0, 0};
+        r->getNumMeshElements(numType);
+        
+        for(int type = 0; type < 5; type++) {
+          MElement *const *el = r->getStartElementType(type);
+          checkValidity(el, numType[type], invalids);
+          _numAnalysedEl += numType[type];
+        }
+      }
+      break;
+    
+    case 2 :
+      Msg::Warning("2D elements must be in a z=cst plane ! If they aren't, results won't be correct.");
+      for (GModel::fiter it = m->firstFace(); it != m->lastFace(); it++) {
+        GFace *f = *it;
+        unsigned int numType[3] = {0, 0, 0};
+        f->getNumMeshElements(numType);
+        
+        for (int type = 0; type < 3; type++) {
+          MElement *const *el = f->getStartElementType(type);
+          checkValidity(el, numType[type], invalids);
+          _numAnalysedEl += numType[type];
+        }
+      }
+      break;
+    
+    case 1 :
+      Msg::Warning("1D elements must be on a y=cst & z=cst line ! If they aren't, results won't be correct.");
+      for (GModel::eiter it = m->firstEdge(); it != m->lastEdge(); it++) {
+        GEdge *e = *it;
+        unsigned int numElement = e->getNumMeshElements();
+        MElement *const *el = e->getStartElementType(0);
+        checkValidity(el, numElement, invalids);
+        _numAnalysedEl += numElement;
+      }
+      break;
+    
+    default :
+      Msg::Error("I can't analyse any element.");
+  }
+  
+  if (toDo % 2) {
+    Msg::Info("Invalids elements :");
+    Msg::Info("-------------------");
+    for (unsigned int i = 0; i < invalids.size(); ++i) {
+      Msg::Info(" %d", invalids[i]->getNum());
+    }
+  }
+  if (toDo / 2 % 2) {
+    Msg::Info("Found %d invalid elements against %d valid", _numInvalid, _numValid);
+    if (_numUncertain) {
+      Msg::Info("%d uncertain elements.", _numUncertain);
+      if (_jacBreak < _bezBreak) {
+        Msg::Info("'JacBreak' is smaller than 'BezBreak'. Change values in order to decrease the number of uncertain elements.");
+      }
+      else {
+        Msg::Info("Increase MaxDepth in order to decrease the number of uncertain elements.");
+      }
+    }
+  }
+  if (toDo / 4 % 2)
+    hideValid_ShowInvalid(invalids);
+}
+
+void GMSH_AnalyseCurvedMeshPlugin::hideValid_ShowInvalid(std::vector<MElement*> &invalids)
+{
+  int current = 0;
+  invalids.push_back(NULL);
+  
+  switch (_dim) {
+    case 3 :
+      for(GModel::riter it = _m->firstRegion(); it != _m->lastRegion(); it++) {
+        GRegion *r = *it;
+        unsigned int numType[5] = {0, 0, 0, 0, 0};
+        r->getNumMeshElements(numType);
+        
+        for(int type = 0; type < 5; type++) {
+          MElement *const *el = r->getStartElementType(type);
+          for (int i = 0; i < numType[type]; ++i) {
+            if (el[i] == invalids[current]) {
+              ++current;
+              el[i]->setVisibility(1);
+            }
+            else
+              el[i]->setVisibility(0);
+          }
+        }
+      }
+      break;
+    
+    case 2 :
+      for (GModel::fiter it = m->firstFace(); it != m->lastFace(); it++) {
+        GFace *f = *it;
+        unsigned int numType[3] = {0, 0, 0};
+        f->getNumMeshElements(numType);
+        
+        for (int type = 0; type < 3; type++) {
+          MElement *const *el = f->getStartElementType(type);
+          for (int i = 0; i < numType[type]; ++i) {
+            if (el[i] == invalids[current]) {
+              ++current;
+              el[i]->setVisibility(1);
+            }
+            else
+              el[i]->setVisibility(0);
+          }
+        }
+      }
+      break;
+    
+    case 1 :
+      for (GModel::eiter it = m->firstEdge(); it != m->lastEdge(); it++) {
+        GEdge *e = *it;
+        unsigned int numElement = e->getNumMeshElements();
+        MElement *const *el = e->getStartElementType(0);
+        for (int i = 0; i < numElement; ++i) {
+          if (el[i] == invalids[current]) {
+            ++current;
+            el[i]->setVisibility(1);
+          }
+          else
+            el[i]->setVisibility(0);
+        }
+      }
+      break;
+    
+    default :
+      break;
+  }
+  invalids.pop_back();
+}
+
+void GMSH_AnalyseCurvedMeshPlugin::computeMinMax()
+{
+  _numAnalysedEl = 0;
+  _numInvalid = 0;
+  _numValid = 0;
+  _numUncertain = 0;
+  _min_Javg = .0, _max_Javg = .0;
+  _min_pJmin = .0, _avg_pJmin = .0;
+  _min_ratioJ = .0, _avg_ratioJ = .0;
+  
+  switch (_dim) {
+    case 3 :
+      for(GModel::riter it = _m->firstRegion(); it != _m->lastRegion(); it++) {
+        GRegion *r = *it;
+        unsigned int numType[5] = {0, 0, 0, 0, 0};
+        r->getNumMeshElements(numType);
+        
+        for(int type = 0; type < 5; type++) {
+          MElement *const *el = r->getStartElementType(type);
+          computeMinMax(el, numType[type]);
+          _numAnalysedEl += numType[type];
+        }
+      }
+      break;
+    
+    case 2 :
+      Msg::Warning("2D elements must be in a z=cst plane ! If they aren't, results won't be correct.");
+      for (GModel::fiter it = m->firstFace(); it != m->lastFace(); it++) {
+        GFace *f = *it;
+        unsigned int numType[3] = {0, 0, 0};
+        f->getNumMeshElements(numType);
+        
+        for (int type = 0; type < 3; type++) {
+          MElement *const *el = f->getStartElementType(type);
+          computeMinMax(el, numType[type]);
+          _numAnalysedEl += numType[type];
+        }
+      }
+      break;
+    
+    case 1 :
+      Msg::Warning("1D elements must be on a y=cst & z=cst line ! If they aren't, results won't be correct.");
+      for (GModel::eiter it = m->firstEdge(); it != m->lastEdge(); it++) {
+        GEdge *e = *it;
+        unsigned int numElement = e->getNumMeshElements();
+        MElement *const *el = e->getStartElementType(0);
+        computeMinMax(el, numElement);
+        _numAnalysedEl += numElement;
+      }
+      break;
+    
+    default :
+      Msg::Error("I can't analyse any element.");
+      return;
+  }
+  Msg::Info("Extrema of J_avg : %g, %g", _min_Javg, _max_Javg);
+	Msg::Info("Minimum of min(distortion) : %g", _min_pJmin);
+	Msg::Info("Average of min(distortion) : %g", _avg_pJmin / _numAnalysedEl);
+	Msg::Info("Minimum of min(J) / max(J) : %g", _min_ratioJ);
+	Msg::Info("Average of min(J) / max(J) : %g", _avg_ratioJ / _numAnalysedEl);
+}
+
 int *GMSH_AnalyseCurvedMeshPlugin::checkJacobian
 (MElement *const *el, int numEl, int maxDepth, int method)
 {
diff --git a/Plugin/AnalyseCurvedMesh.h b/Plugin/AnalyseCurvedMesh.h
index 63de47ec1444fff985c7649c0f4da86d8f61f41e..05da9831a3079f7e809d3104d3efb4299fcd6923 100644
--- a/Plugin/AnalyseCurvedMesh.h
+++ b/Plugin/AnalyseCurvedMesh.h
@@ -17,28 +17,49 @@ extern "C"
 
 class GMSH_AnalyseCurvedMeshPlugin : public GMSH_PostPlugin
 {
- public:
-  GMSH_AnalyseCurvedMeshPlugin(){}
-  std::string getName() const { return "AnalyseCurvedMesh"; }
-  std::string getShortHelp() const
-  {
-    return "Check that the curved mesh isn't wretched";
-  }
-  std::string getHelp() const;
-  std::string getAuthor() const { return "Amaury Johnen"; }
-  int getNbOptions() const;
-  StringXNumber *getOption(int);  
-  PView *execute(PView *);
-  bool isJacPositive(MElement *);
-  int method_1_1(MElement *, int depth);
-  int method_1_2(MElement *, int depth);
-  int method_1_3(MElement *, int depth);
-  void method_2_2(MElement *const *, std::vector<int> &tags, int depth);
-  void method_2_3(MElement *const *, std::vector<int> &tags, int depth);
-  //int checkJacobian(MElement *, int depth);
-  //int *checkJacobian2(MElement *const *, int numEl, int depth);
-  int *checkJacobian(MElement *const *, int numEl, int depth, int method);
-  int division(const bezierBasis *, const fullVector<double> &, int depth);
+  private :
+    int _dim;
+    GModel *_m;
+    int _maxDepth;
+    double _jacBreak, _bezBreak, _tol;
+    
+    int _numAnalysedEl;
+    int _numInvalid, _numValid, _numUncertain;
+    double _min_Javg, _max_Javg;
+    double _min_pJmin, _avg_pJmin;
+    double _min_ratioJ, _avg_ratioJ;
+    
+  public :
+    GMSH_AnalyseCurvedMeshPlugin(){}
+    std::string getName() const { return "AnalyseCurvedMesh"; }
+    std::string getShortHelp() const
+    {
+      return "Check validity of elements and/or compute min&max of the jacobian";
+    }
+    std::string getHelp() const;
+    std::string getAuthor() const { return "Amaury Johnen"; }
+    int getNbOptions() const;
+    StringXNumber *getOption(int);  
+    PView *execute(PView *);
+    void checkValidity(MElement *const *, int numEl, std::vector<MElement*> &invalids);
+    
+  private :
+    void checkValidity(int toDo);
+    void computeMinMax();
+    void checkValidity(MElement *const *, int numEl, std::vector<MElement*> &invalids);
+    void computeMinMax(MElement *const *, int numEl);
+    void hideValid_ShowInvalid(std::vector<MElement*> &invalids);
+    /*bool isJacPositive(MElement *);
+    int method_1_1(MElement *, int depth);
+    int method_1_2(MElement *, int depth);
+    int method_1_3(MElement *, int depth);
+    void method_2_2(MElement *const *, std::vector<int> &tags, int depth);
+    void method_2_3(MElement *const *, std::vector<int> &tags, int depth);
+    //int checkJacobian(MElement *, int depth);
+    //int *checkJacobian2(MElement *const *, int numEl, int depth);
+    int *checkJacobian(MElement *const *, int numEl, int depth, int method);
+    int division(const bezierBasis *, const fullVector<double> &, int depth);
+    */
 };
 
 #endif