From afef7ddb09b832c83864b136213baaa28cf37bff Mon Sep 17 00:00:00 2001
From: Christophe Palmann <christophe.palmann@c-s.fr>
Date: Fri, 28 Nov 2014 12:12:15 +0100
Subject: [PATCH] ENH: bandmathx app, make sure that only one expression (or
 one meta-expression -semicolons-) will be used

---
 Applications/Utils/otbBandMathX.cxx           | 25 ++++++++++---------
 Code/BasicFilters/otbBandMathXImageFilter.h   |  5 ++++
 Code/BasicFilters/otbBandMathXImageFilter.txx | 18 ++++++++++---
 3 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/Applications/Utils/otbBandMathX.cxx b/Applications/Utils/otbBandMathX.cxx
index df32322d70..5f00de72a5 100644
--- a/Applications/Utils/otbBandMathX.cxx
+++ b/Applications/Utils/otbBandMathX.cxx
@@ -52,7 +52,7 @@ private:
   {
     SetName("BandMathX");
     SetDescription("This application performs mathematical operations on multiband images.\n"
-      "Mathematical formula interpretation is done via muParserX libraries https://code.google.com/p/muparserx/");
+      "Mathematical formula interpretation is done via muParserX library : http://articles.beltoforion.de/article.php?a=muparserx");
 
     SetDocName("Band Math X");
     SetDocLongDescription("The goal of this documentation is to give the user some hints about the syntax used in this application.\n"
@@ -95,10 +95,10 @@ private:
       "- J is an number identifying the band (remember, first band is indexed by 1)\n"
       "- KxP are two numbers that represent the size of the neighborhood (first one is related to the horizontal direction)\n"
       "All neighborhood are centred, thus K and P must be odd numbers.\n"
-      "Many operators come with this new functionnality: conv, mean var median min max...\n"
+      "Many operators come with this new functionnality: dotpr, mean var median min max...\n"
       "For instance, if im1 represents the pixel of 3 bands image:\n\n"
       "               im1 - mean(im1b1N5x5,im1b2N5x5,im1b3N5x5)       (3)\n"
-      "\ncould represent a high pass filter (Note that by implying three neighborhoods, the operator returned a row vector of three components.\n"
+      "\ncould represent a high pass filter (Note that by implying three neighborhoods, the operator mean returns a row vector of three components.\n"
       "It is a typical behaviour for many operators of this application).\n"
 
       "\n\n"
@@ -115,18 +115,17 @@ private:
 
       "\n\n"
       "- Application itself:\n\n"
-      "The application takes the following parameters :"
+      "The application takes the following parameters :\n"
       "- Setting the list of inputs can be done with the 'il' parameter.\n"
-      "- Setting expressions can be done with the 'exp' parameter. Separating expressions by semi-colons (; ) will concatenate their results into one multiband output image.\n"
-      "Adding expressions without the use of semi-colons will produce additional output images.\n"
-      "- Setting constants can be done with the 'incontext' parameter. User must provide a txt file with a specific syntax: #type name value\n"
+      "- Setting expressions can be done with the 'exp' parameter (see also limitations section below).\n"
+      "- Setting constants can be done with the 'incontext' parameter. User must provide a txt file with a specific syntax: #type name value\n"    
       "An example of such a file is given below:\n\n"
       "#F expo 1.1\n"
       "#M kernel1 { 0.1 , 0.2 , 0.3; 0.4 , 0.5 , 0.6; 0.7 , 0.8 , 0.9; 1 , 1.1 , 1.2; 1.3 , 1.4 , 1.5 }\n"
       "\nAs we can see,  #I/#F allows the definition of an integer/float constant, whereas #M allows the definition of a vector/matrix.\n"
       "In the latter case, elements of a row must be separated by commas, and rows must be separated by semicolons.\n"
-      "It is also possible to define expressions within the same txt file, with the pattern #E expr; they will be added to the list of expressions to be applied. For instance:\n\n"
-      "#E conv(kernel1,im1b1N3x5); im2b1^expo\n"
+      "It is also possible to define expressions within the same txt file, with the pattern #E expr. For instance (two expressions; see also limitations section below):\n\n"
+      "#E dotpr(kernel1,im1b1N3x5) ; im2b1^expo\n"
       "\n- The 'outcontext' parameter allows to save user's constants and expressions (context).\n"
       "- Setting the output image can be done with the 'out' parameter (multi-outputs is not implemented yet).\n"
       "\n\n"
@@ -134,7 +133,8 @@ private:
 
 );
 
-    SetDocLimitations("Only one output is possible (to be improved)");
+    SetDocLimitations("The application is currently unable to produce one output image per expression, contrary to otbBandMathXImageFilter.\n"
+                      "Separating expressions by semi-colons (;) will concatenate their results into a unique multiband output image. ");
     SetDocAuthors("OTB-Team");
     SetDocSeeAlso(" ");
     AddDocTag("Util");
@@ -147,9 +147,9 @@ private:
 
     AddRAMParameter();
 
-    AddParameter(ParameterType_StringList, "exp", "Expressions");
+    AddParameter(ParameterType_String, "exp", "Expressions");
     SetParameterDescription("exp",
-                            "Mathematical expressions to apply.");
+                            "Mathematical expression to apply.");
     MandatoryOff("exp");
 
     AddParameter(ParameterType_InputFilename, "incontext", "Import context");
@@ -192,6 +192,7 @@ private:
     }
 
     m_Filter               = BandMathImageFilterType::New();
+    m_Filter->SetManyExpressions(false);
 
     for (unsigned int i = 0; i < nbImages; i++)
       {
diff --git a/Code/BasicFilters/otbBandMathXImageFilter.h b/Code/BasicFilters/otbBandMathXImageFilter.h
index b6d8dca957..c888ea40e0 100644
--- a/Code/BasicFilters/otbBandMathXImageFilter.h
+++ b/Code/BasicFilters/otbBandMathXImageFilter.h
@@ -98,6 +98,9 @@ public:
   /** Return a pointer on the nth filter input */
   ImageType * GetNthInput(unsigned int idx);
 
+  /** Set an expression to be parsed */
+  void SetManyExpressions(bool flag);
+
   /** Set an expression to be parsed */
   void SetExpression(const std::string& expression);
 
@@ -173,6 +176,8 @@ private :
   itk::Array<long>                      m_ThreadUnderflow;
   itk::Array<long>                      m_ThreadOverflow;
 
+  bool                                  m_ManyExpressions;
+
 };
 
 }//end namespace otb
diff --git a/Code/BasicFilters/otbBandMathXImageFilter.txx b/Code/BasicFilters/otbBandMathXImageFilter.txx
index 81f0849b4b..e51d1d9ae2 100644
--- a/Code/BasicFilters/otbBandMathXImageFilter.txx
+++ b/Code/BasicFilters/otbBandMathXImageFilter.txx
@@ -63,6 +63,8 @@ BandMathXImageFilter<TImage>
   m_VAllowedVarNameAuto.push_back(ahcY);
 
   m_SizeNeighbourhood=10;
+  
+  m_ManyExpressions = true;
 
 }
 
@@ -217,11 +219,18 @@ TImage * BandMathXImageFilter<TImage>
   return const_cast<TImage *>(this->GetInput(idx));
 }
 
+template< typename TImage >
+void BandMathXImageFilter<TImage>
+::SetManyExpressions(bool flag)
+{
+    m_ManyExpressions = flag;
+}
 
 template< typename TImage >
 void BandMathXImageFilter<TImage>
 ::SetExpression(const std::string& expression)
 {
+  std::string expressionToBePushed = expression;
 
   if (expression.find(";") != std::string::npos)
   {
@@ -234,11 +243,12 @@ void BandMathXImageFilter<TImage>
         oss << expression[i];
 
     oss << ")";
-    m_Expression.push_back(oss.str());
-
   }
-  else
-    m_Expression.push_back(expression);
+
+  if (m_ManyExpressions)
+    m_Expression.push_back(expressionToBePushed);
+  else if (m_Expression.size() == 0)
+    m_Expression.push_back(expressionToBePushed);
 
   if (m_Expression.size()>1)
     this->SetNthOutput( (int) (m_Expression.size()) -1, ( TImage::New() ).GetPointer() );
-- 
GitLab