Commit fcdfd63c authored by Antoine Regimbeau's avatar Antoine Regimbeau

Merge branch 'crash_bandmathx' into 'develop'

Crash bandmathx

Closes #1949

See merge request !567
parents 638fc44c 4ccbe60f
Pipeline #2389 passed with stages
in 8 minutes and 28 seconds
#E cos(im1b1)+im2b1*im3b1-im3b2+ndvi(im3b3,im3b4)
#F val 1
#E im1b1 + 2*val + im2b1
......@@ -246,54 +246,42 @@ private:
void DoUpdateParameters() override
{
// check if input context should be used
bool useContext = this->ContextCheck();
bool context_exists = this->ContextCheck();
// Check if the expression is correctly set
if (HasValue("il") && HasValue("exp"))
{
this->LiveCheck(useContext);
}
BandMathImageFilterType::Pointer math_filter = BandMathImageFilterType::New();
math_filter->SetManyExpressions(false);
// first thing, load context if there is one
if (context_exists)
math_filter->ImportContext(GetParameterString("incontext"));
// Only one expression is allowed '-exp'>'-incontext'
if ( !HasValue("exp") )
SetParameterString("exp", math_filter->GetExpression(0));
if ( HasValue("il") && HasValue("exp") )
{
math_filter->ClearExpression(); // remove expression set by context
math_filter->SetExpression(GetParameterString("exp")); //set expression
LiveCheck(math_filter);
}
}
// Check if the given filename is valid
bool ContextCheck(void)
{
bool useContext = false;
{
bool context_exists = false;
if (IsParameterEnabled("incontext") && HasValue("incontext"))
{
{
std::string contextPath = GetParameterString("incontext");
// check that file exists
if (itksys::SystemTools::FileExists(contextPath,true))
{
BandMathImageFilterType::Pointer dummyFilter =
BandMathImageFilterType::New();
dummyFilter->SetManyExpressions(false);
try
{
dummyFilter->ImportContext(contextPath);
useContext = true;
}
catch(itk::ExceptionObject& err)
{
//trick to prevent unreferenced local variable warning on MSVC
(void)err;
// silent catch
useContext = false;
}
if (useContext)
{
// only set the first expression, 'ManyExpression' is disabled.
this->SetParameterString("exp",dummyFilter->GetExpression(0));
}
}
{
context_exists = true;
}
return useContext;
}
return context_exists;
}
void LiveCheck(bool useContext=false)
void LiveCheck( BandMathImageFilterType::Pointer math_filter )
{
BandMathImageFilterType::Pointer dummyFilter =
BandMathImageFilterType::New();
dummyFilter->SetManyExpressions(false);
std::vector<MultiChannelExtractorType::Pointer> extractors;
FloatVectorImageListType::Pointer inList = GetParameterImageList("il");
for (unsigned int i = 0; i < inList->Size(); i++)
......@@ -314,19 +302,11 @@ private:
{
extract->SetChannel(j+1);
}
dummyFilter->SetNthInput(i,extract->GetOutput());
}
if (useContext)
{
dummyFilter->ImportContext(GetParameterString("incontext"));
}
else
{
dummyFilter->SetExpression(GetParameterString("exp"));
math_filter->SetNthInput(i,extract->GetOutput());
}
try
{
dummyFilter->UpdateOutputInformation();
math_filter->UpdateOutputInformation();
SetParameterDescription("exp", "Valid expression");
}
catch(itk::ExceptionObject& err)
......@@ -334,8 +314,15 @@ private:
// Change the parameter description to be able to have the
// parser errors in the tooltip
SetParameterDescription("exp", err.GetDescription());
// std::string error_string(err.GetDescription());
// otbAppLogINFO("There was an error while parsing the expression given "
// "its input:" + error_string );
}
catch(...)
{
SetParameterDescription("exp", "Other exception catched");
}
}
void DoExecute() override
{
......@@ -352,11 +339,11 @@ private:
if ( (!IsParameterEnabled("exp")) && (!IsParameterEnabled("incontext")) )
{
itkExceptionMacro("No expression set...; please set and enable at least one one expression");
itkExceptionMacro("No expression set...; please set and enable at least one expression");
}
m_Filter = BandMathImageFilterType::New();
m_Filter->SetManyExpressions(false);
BandMathImageFilterType::Pointer math_filter = BandMathImageFilterType::New();
math_filter->SetManyExpressions(false);
for (unsigned int i = 0; i < nbImages; i++)
{
......@@ -367,31 +354,33 @@ private:
<< currentImage->GetNumberOfComponentsPerPixel()
<< " components");
m_Filter->SetNthInput(i,currentImage);
math_filter->SetNthInput(i,currentImage);
}
bool useContext = this->ContextCheck();
bool context_exists = this->ContextCheck();
// first thing, load context if there is one
if (context_exists)
{
std::string context_string = GetParameterString("incontext");
math_filter->ImportContext(context_string);
otbAppLogINFO("Using Context: " << context_string
<< " for variables (and expression if no parameter -exp has been given)." );
}
// Only one expression is allowed '-exp'>'-incontext'
math_filter->ClearExpression(); // remove expression set by context
std::string expStr = GetParameterString("exp");
if (useContext)
{
otbAppLogINFO("Using input context: " << expStr );
m_Filter->ImportContext(GetParameterString("incontext"));
}
else
{
otbAppLogINFO("Using expression: " << expStr );
m_Filter->SetExpression(expStr);
}
otbAppLogINFO("Using expression: " << expStr );
math_filter->SetExpression(expStr);
if ( IsParameterEnabled("outcontext") && HasValue("outcontext") )
m_Filter->ExportContext(GetParameterString("outcontext"));
math_filter->ExportContext(GetParameterString("outcontext"));
// Set the output image
SetParameterOutputImage("out", m_Filter->GetOutput());
SetParameterOutputImage("out", math_filter->GetOutput());
RegisterPipeline();
}
BandMathImageFilterType::Pointer m_Filter;
};
} // namespace Wrapper
......
......@@ -26,6 +26,9 @@ otb_module(OTBAppMathParserX
OTBMathParserX
OTBObjectList
TEST_DEPENDS
OTBTestKernel
DESCRIPTION
"${DOCUMENTATION}"
)
......@@ -20,15 +20,15 @@
otb_module_test()
#----------- BandMathX TESTS ----------------
otb_test_application(NAME apTvUtBandMathX
APP BandMathX
OPTIONS -il ${INPUTDATA}/poupees_sub_c1.png
${INPUTDATA}/poupees_sub_c2.png
${INPUTDATA}/poupees_sub.png
-out ${TEMP}/apTvUtBandMathXOutput.tif
-incontext ${INPUTDATA}/apTvUtExportBandMathX.txt
VALID --compare-image ${NOTOL}
${INPUTDATA}/apTvUtBandMathOutput.tif
${TEMP}/apTvUtBandMathXOutput.tif)
set(OTBBandMathXAppTest
otbBandMathXAppTests.cxx
)
add_executable(OTBBandMathXAppTest ${OTBBandMathXAppTest})
target_link_libraries(OTBBandMathXAppTest ${OTBAppMathParserX-Test_LIBRARIES})
otb_module_target_label(OTBBandMathXAppTest)
otb_add_test(NAME apTvUtBandMathX COMMAND OTBBandMathXAppTest
$<TARGET_FILE_DIR:otbapp_BandMathX>
${INPUTDATA}/apTvUtExportBandMathX.txt
)
\ No newline at end of file
/*
* Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
*
* This file is part of Orfeo Toolbox
*
* https://www.orfeo-toolbox.org/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "otbVectorImage.h"
#include "otbWrapperApplicationRegistry.h"
#include "otbWrapperTypes.h"
#include <string>
typedef otb::VectorImage<unsigned char> VectorImageType;
typedef VectorImageType::PixelType PixelType;
/* This function is creating and filling a vector image */
VectorImageType::Pointer create_vector_image( int pxl_s , int nb_comp , unsigned char value )
{
VectorImageType::SizeType size;
size.Fill(pxl_s);
VectorImageType::IndexType index;
index.Fill(0);
VectorImageType::RegionType region;
region.SetSize(size);
region.SetIndex(index);
VectorImageType::Pointer image = VectorImageType::New();
image->SetLargestPossibleRegion( region );
image->SetBufferedRegion( region );
image->SetRequestedRegion( region );
image->SetNumberOfComponentsPerPixel(nb_comp);
image->Allocate();
PixelType val(nb_comp);
val.Fill(value);
image->FillBuffer(val);
return image;
}
#define dyn_cast( im_base , vect_im ) \
{ \
vect_im = dynamic_cast<otb::VectorImage<float> *>(im_base); \
if( ! vect_im ) \
{ \
std::cout<<"Not the right conversion, cannot retrieve the output"<<std::endl; \
return EXIT_FAILURE ; \
} \
}
int main(int , char * argv[] )
{
std::cout<<"Begin bandMathX Test"<<std::endl;
int return_val = 0;
auto img1 = create_vector_image(5,2,1);
auto img2 = create_vector_image(5,1,2);
VectorImageType::IndexType index;
index.Fill(3); // Center of the images
std::cout<<"Create application"<<std::endl;
otb::Wrapper::ApplicationRegistry::SetApplicationPath(argv[1]);
auto app = otb::Wrapper::ApplicationRegistry::CreateApplication("BandMathX");
app->AddImageToParameterInputImageList("il", img1);
app->UpdateParameters();
app->AddImageToParameterInputImageList("il", img2);
app->UpdateParameters();
std::cout<<"Inputs are set"<<std::endl;
// Case one: only expression
app->SetParameterString("exp", "im1b1+im2b1");
app->UpdateParameters();
app->SetParameterOutputImagePixelType("out", otb::Wrapper::ImagePixelType::ImagePixelType_uint8);
std::cout<<"Case one: parameter exp is set"<<std::endl;
app->Execute();
auto output = app->GetParameterImageBase("out");
output->Update();
float im_val = 0;
// We need to be carefull as we are taking the direct output of the underlying
// filter in the application
otb::VectorImage<float> * output_int = nullptr;
dyn_cast( output , output_int )
im_val = output_int->GetPixel(index).GetElement(0);
if ( im_val != 3 )
{
std::cout<<"Wrong value in test, was expecting 3, got "<<im_val<<std::endl;
return_val++;
}
else
{
std::cout<<"Case one passed"<<std::endl;
}
// Case two: expression and context
app->SetParameterString("exp", "im1b1+val-im2b1");
app->UpdateParameters();
std::cout<<"Case two: use context to define a constant"<<std::endl;
auto desc = app->GetParameterDescription("exp");
if (desc.find("Following variables not allowed : val") == std::string::npos)
{
std::cout<<"Cannot find usual value in the parameter description."<<std::endl;
std::cout<<"The test was looking for \"Following variables not allowed : val\""
<<" in the parameter description and got \""<<desc<<"\" instead."<<std::endl;
return_val++;
}
app->SetParameterString("incontext",argv[2]);
// val is set in the context to 1
app->UpdateParameters();
desc = app->GetParameterDescription("exp");
if (desc.find("Valid expression") == std::string::npos )
{
std::cout<<"Cannot find usual value in the parameter description."<<std::endl;
std::cout<<"The test was looking for \"Valid expression\""
<<" in the parameter description and got \""<<desc<<"\" instead."<<std::endl;
return_val++;
}
app->Execute();
output = app->GetParameterImageBase("out");
output->Update();
// We need to be carefull as we are taking the direct output of the underlying
// filter in the application
dyn_cast( output , output_int )
im_val = output_int->GetPixel(index).GetElement(0);
if ( im_val != 0 )
{
std::cout<<"Wrong value in test, was expecting 0, got "<<im_val<<std::endl;
return_val++;
}
else
{
std::cout<<"Case two passed"<<std::endl;
}
// Case three: no expression and context
app->SetParameterString("exp", "");
app->UpdateParameters();
std::cout<<"Case three: no parameter exp"<<std::endl;
auto exp = app->GetParameterString("exp");
if (exp.find("im1b1 + 2*val + im2b1") == std::string::npos )
{
std::cout<<"The expression value is not set correctly."<<std::endl;
std::cout<<"The test was looking for \"im1b1 + 2*val + im2b1\""
<<" in the parameter value and got \""<<exp<<"\" instead."<<std::endl;
return_val++;
}
app->Execute();
output = app->GetParameterImageBase("out");
output->Update();
// We need to be carefull as we are taking the direct output of the underlying
// filter in the application
dyn_cast( output , output_int )
im_val = output_int->GetPixel(index).GetElement(0);
if (im_val != 5 )
{
std::cout<<"Wrong value in test, was expecting 5, got "<<im_val<<std::endl;
return_val++;
}
else
{
std::cout<<"Case three passed"<<std::endl;
}
return return_val;
}
\ No newline at end of file
......@@ -112,8 +112,8 @@ public:
/** Set an expression to be parsed */
void SetExpression(const std::string& expression);
/** Return the nth expression to be parsed */
std::string GetExpression(int) const;
/** Return the nth expression to be parsed*/
std::string GetExpression(unsigned int IDExpression) const;
/** Set a matrix (or a vector) */
void SetMatrix(const std::string& name, const std::string& definition);
......@@ -127,9 +127,15 @@ public:
/** Import constants and expressions from a given filename */
void ImportContext(const std::string& filename);
/** Clear all previously set expression*/
void ClearExpression();
/** Return the variable and constant names */
std::vector<std::string> GetVarNames() const;
bool GlobalStatsDetected() const
{
return !m_StatsVarDetected.empty();
}
protected :
BandMathXImageFilter();
......@@ -145,11 +151,6 @@ protected :
private :
bool globalStatsDetected() const
{
return (m_StatsVarDetected.size()>0);
}
typedef struct {
std::string name;
ValueType value;
......
......@@ -261,7 +261,13 @@ void BandMathXImageFilter<TImage>
this->Modified();
}
template< typename TImage >
void BandMathXImageFilter<TImage>
::ClearExpression()
{
m_Expression.clear();
this->Modified();
}
template< typename TImage >
void BandMathXImageFilter<TImage>
::SetMatrix(const std::string& name, const std::string& definition)
......@@ -517,9 +523,11 @@ void BandMathXImageFilter<TImage>
template< typename TImage >
std::string BandMathXImageFilter<TImage>
::GetExpression(int IDExpression) const
::GetExpression(unsigned int IDExpression) const
{
return m_Expression[IDExpression];
if ( IDExpression < m_Expression.size() )
return m_Expression[IDExpression];
return "";
}
......@@ -913,7 +921,7 @@ void BandMathXImageFilter< TImage >
CheckImageDimensions();
PrepareParsers();
if (globalStatsDetected())
if (GlobalStatsDetected())
PrepareParsersGlobStats();
OutputsDimensions();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment