diff --git a/app/otbSARCorrelationGrid.cxx b/app/otbSARCorrelationGrid.cxx
index ca3c8b43206900f5b078e5f51ff0814cd112af4a..27bf3628879405f7baf4335b7e0bb0124529f683 100644
--- a/app/otbSARCorrelationGrid.cxx
+++ b/app/otbSARCorrelationGrid.cxx
@@ -21,9 +21,10 @@
 #include "otbWrapperApplication.h"
 #include "otbWrapperApplicationFactory.h"
 
+#include "itkMacro.h"
 #include "itkFFTNormalizedCorrelationImageFilter.h"
-#include "itkMinimumMaximumImageCalculator.h"
 
+#include "otbSARStreamingMaximumMinimumImageFilter.h"
 #include "otbSARTemporalCorrelationGridImageFilter.h"
 
 #include <iostream>
@@ -46,7 +47,7 @@ public:
 
   // Filters
   typedef itk::FFTNormalizedCorrelationImageFilter<FloatImageType, FloatImageType>          CorFilterType;
-  typedef itk::MinimumMaximumImageCalculator< FloatImageType>			            MinMaxCalculatorType;
+  typedef otb::SARStreamingMaximumMinimumImageFilter< FloatImageType>		   MinMaxFilterType;
   typedef otb::SARTemporalCorrelationGridImageFilter<FloatImageType, FloatVectorImageType>  CorGridFilterType;
   
 
@@ -134,28 +135,41 @@ void DoExecute() override
   otbAppLogINFO(<<"ML Factor on range : "<<factorML_ran);
   otbAppLogINFO(<<"Grid Step for range : "<<grid_step_ran);
   otbAppLogINFO(<<"Grid Step for azimut : "<<grid_step_azi);
-
+ 
   // Get master and slave image
   FloatImageType::Pointer MasterPtr = GetParameterFloatImage("inmaster");
   FloatImageType::Pointer SlavePtr = GetParameterFloatImage("inslave");
    
-  
+  // Check input size (Master size) to protect memory. 
+  // If size > 15000 raise an exception and indicate more appropriate ml factors
+  if (MasterPtr->GetLargestPossibleRegion().GetSize()[0] > 15000 || 
+      MasterPtr->GetLargestPossibleRegion().GetSize()[1] > 15000)
+    {
+      // integer divisions
+      int intermediate_mlran = MasterPtr->GetLargestPossibleRegion().GetSize()[0]/15000 + 1;
+      int intermediate_mlazi = MasterPtr->GetLargestPossibleRegion().GetSize()[1]/15000 + 1;
+
+      otbAppLogCRITICAL(<<"ML Factors are not appropriate for these estimations. Please use other factors such as : "<< intermediate_mlran << " x " << intermediate_mlazi );
+
+      itkExceptionMacro(<<"ML Factors are not appropriate for these estimations");
+    }
+
   // Correlation Filter
   CorFilterType::Pointer correlationFilter = CorFilterType::New();
   m_Ref.push_back(correlationFilter.GetPointer());
   correlationFilter->SetFixedImage(MasterPtr);
   correlationFilter->SetMovingImage(SlavePtr);
-  correlationFilter->Update();
-
-  // Min/Max calculator
-  MinMaxCalculatorType::Pointer minMaxFilter = MinMaxCalculatorType::New();
-  minMaxFilter->SetImage(correlationFilter->GetOutput());
-  minMaxFilter->ComputeMaximum();
+  
+  MinMaxFilterType::Pointer minMaxFilter = MinMaxFilterType::New();
+  minMaxFilter->SetInput(correlationFilter->GetOutput());
+  // Adapt streaming with ram parameter (default 256 MB)
+  minMaxFilter->GetStreamer()->SetAutomaticStrippedStreaming(GetParameterInt("ram"));
+  minMaxFilter->Update();
 
   float shiftML_range = ((correlationFilter->GetOutput()->GetLargestPossibleRegion().GetSize()[0]/2.)-
-			  minMaxFilter->GetIndexOfMaximum()[0]);
+			  minMaxFilter->GetIndexOfMax()[0]);
   float shiftML_azimut = ((correlationFilter->GetOutput()->GetLargestPossibleRegion().GetSize()[1]/2.)
-  -minMaxFilter->GetIndexOfMaximum()[1]);
+			   -minMaxFilter->GetIndexOfMax()[1]);
 
   // Correlation Grid Filter 
   CorGridFilterType::Pointer filterCorrelationGrid = CorGridFilterType::New();
diff --git a/app/otbSARCorrelationRough.cxx b/app/otbSARCorrelationRough.cxx
index 15e767fd643727b50765bd54156cd1900ded66dd..36f6668a45d476278296e0be5e3871162b1dc008 100644
--- a/app/otbSARCorrelationRough.cxx
+++ b/app/otbSARCorrelationRough.cxx
@@ -21,8 +21,10 @@
 #include "otbWrapperApplication.h"
 #include "otbWrapperApplicationFactory.h"
 
+#include "itkMacro.h"
 #include "itkFFTNormalizedCorrelationImageFilter.h"
-#include "itkMinimumMaximumImageCalculator.h"
+
+#include "otbSARStreamingMaximumMinimumImageFilter.h"
 
 #include <iostream>
 #include <string>
@@ -43,8 +45,8 @@ public:
   itkTypeMacro(SARCorrelationRough, otb::Wrapper::Application);
 
   // Filters
-typedef itk::FFTNormalizedCorrelationImageFilter<FloatImageType, FloatImageType> CorFilterType;
-typedef itk::MinimumMaximumImageCalculator< FloatImageType>			    MinMaxCalculatorType;
+  typedef itk::FFTNormalizedCorrelationImageFilter<FloatImageType, FloatImageType> CorFilterType;
+  typedef otb::SARStreamingMaximumMinimumImageFilter< FloatImageType>		   MinMaxFilterType;
 
 private:
   void DoInit() override
@@ -124,32 +126,49 @@ void DoExecute() override
   otbAppLogINFO(<<"ML Factor on azimut :"<<factorML_azi);
   otbAppLogINFO(<<"ML Factor on range : "<<factorML_ran);
 
+  otbAppLogINFO(<<"RAM : "<< GetParameterInt("ram"));
+
   // Get master and slave image
   FloatImageType::Pointer MasterPtr = GetParameterFloatImage("inmaster");
   FloatImageType::Pointer SlavePtr = GetParameterFloatImage("inslave");
-   
+  
+  // Check input size (Master size) to protect memory. 
+  // If size > 15000 raise an exception and indicate more appropriate ml factors
+  if (MasterPtr->GetLargestPossibleRegion().GetSize()[0] > 15000 || 
+      MasterPtr->GetLargestPossibleRegion().GetSize()[1] > 15000)
+    {
+      // integer divisions
+      int intermediate_mlran = MasterPtr->GetLargestPossibleRegion().GetSize()[0]/15000 + 1;
+      int intermediate_mlazi = MasterPtr->GetLargestPossibleRegion().GetSize()[1]/15000 + 1;
+
+      otbAppLogCRITICAL(<<"ML Factors are not appropriate for these estimations. Please use other factors such as : "<< intermediate_mlran << " x " << intermediate_mlazi );
+
+      itkExceptionMacro(<<"ML Factors are not appropriate for these estimations");
+    }
+ 
   
   // Correlation Filter
   CorFilterType::Pointer correlationFilter = CorFilterType::New();
   m_Ref.push_back(correlationFilter.GetPointer());
   correlationFilter->SetFixedImage(MasterPtr);
   correlationFilter->SetMovingImage(SlavePtr);
-  correlationFilter->Update();
 
-  // Min/Max calculator
-  MinMaxCalculatorType::Pointer minMaxFilter = MinMaxCalculatorType::New();
-  minMaxFilter->SetImage(correlationFilter->GetOutput());
-  minMaxFilter->ComputeMaximum();
+  MinMaxFilterType::Pointer minMaxFilter = MinMaxFilterType::New();
+  minMaxFilter->SetInput(correlationFilter->GetOutput());
+  // Adapt streaming with ram parameter (default 256 MB)
+  minMaxFilter->GetStreamer()->SetAutomaticStrippedStreaming(GetParameterInt("ram"));
+  minMaxFilter->Update();
+
 
   float shiftSLC_range = ((correlationFilter->GetOutput()->GetLargestPossibleRegion().GetSize()[0]/2.)-
-		       minMaxFilter->GetIndexOfMaximum()[0]) * static_cast<float>(factorML_ran);
+		       minMaxFilter->GetIndexOfMax()[0]) * static_cast<float>(factorML_ran);
   float shiftSLC_azimut = ((correlationFilter->GetOutput()->GetLargestPossibleRegion().GetSize()[1]/2.)
-			-minMaxFilter->GetIndexOfMaximum()[1]) * static_cast<float>(factorML_azi);
+			-minMaxFilter->GetIndexOfMax()[1]) * static_cast<float>(factorML_azi);
 
   float shiftML_range = ((correlationFilter->GetOutput()->GetLargestPossibleRegion().GetSize()[0]/2.)-
-			  minMaxFilter->GetIndexOfMaximum()[0]);
+			  minMaxFilter->GetIndexOfMax()[0]);
   float shiftML_azimut = ((correlationFilter->GetOutput()->GetLargestPossibleRegion().GetSize()[1]/2.)
-			   -minMaxFilter->GetIndexOfMaximum()[1]);
+			   -minMaxFilter->GetIndexOfMax()[1]);
 
   // Assigne Outputs
   SetParameterFloat("shiftranslc", shiftSLC_range);
diff --git a/app/otbSARFineDeformationGrid.cxx b/app/otbSARFineDeformationGrid.cxx
index cbbe0cb697f4ddd47a8cc1692a0bd287c96c4416..b65d7e951fb41bbebaa88cb3b63433f0f422f192 100644
--- a/app/otbSARFineDeformationGrid.cxx
+++ b/app/otbSARFineDeformationGrid.cxx
@@ -193,6 +193,7 @@ private:
     GetInternalApplication("CorGridApp")->SetParameterInt("mlazi", factor_azi);
     GetInternalApplication("CorGridApp")->SetParameterInt("gridsteprange", grid_step_ran);
     GetInternalApplication("CorGridApp")->SetParameterInt("gridstepazimut", grid_step_azi);
+    GetInternalApplication("CorGridApp")->SetParameterInt("ram", GetParameterInt("ram"));
     //if (demGridToFavor)
       {
 	GetInternalApplication("CorGridApp")->SetParameterInt("nooffset", 1);
@@ -215,6 +216,7 @@ private:
     GetInternalApplication("DEMGridApp")->SetParameterInt("mlazi", factor_azi);
     GetInternalApplication("DEMGridApp")->SetParameterInt("gridsteprange", grid_step_ran);
     GetInternalApplication("DEMGridApp")->SetParameterInt("gridstepazimut", grid_step_azi);
+    GetInternalApplication("DEMGridApp")->SetParameterInt("ram", GetParameterInt("ram"));
     ExecuteInternal("DEMGridApp");
     
     // Third (and last) application : SARMultiLook
@@ -225,6 +227,7 @@ private:
     GetInternalApplication("CorrectionGridApp")->SetParameterFloat("threshold", threshold);
     GetInternalApplication("CorrectionGridApp")->SetParameterFloat("gap", gap);
     GetInternalApplication("CorrectionGridApp")->SetParameterString("advantage", advantage);
+    GetInternalApplication("CorrectionGridApp")->SetParameterInt("ram", GetParameterInt("ram"));
     ExecuteInternal("CorrectionGridApp");
     
     // Retrive the output of CorrectionGridApp
diff --git a/include/otbSARStreamingMaximumMinimumImageFilter.h b/include/otbSARStreamingMaximumMinimumImageFilter.h
new file mode 100644
index 0000000000000000000000000000000000000000..13861e63f04f452eec0877ebf6ddd90090aed616
--- /dev/null
+++ b/include/otbSARStreamingMaximumMinimumImageFilter.h
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2005-2018 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.
+ */
+
+#ifndef otbSARStreamingMaximumMinimumImageFilter_h
+#define otbSARStreamingMaximumMinimumImageFilter_h
+
+#include "otbPersistentImageFilter.h"
+#include "itkNumericTraits.h"
+#include "itkArray.h"
+#include "itkSimpleDataObjectDecorator.h"
+#include "otbPersistentFilterStreamingDecorator.h"
+
+#include <complex>
+#include <cmath>
+
+namespace otb
+{
+
+/** \class PersistentMaximumMinimumImageFilter
+ * \brief Estimate some values for an input image (min/max and corresponding indexes).
+ * 
+ * This filter persists its temporary data. It means that if you Update it n times on n different
+ * requested regions, the output statistics will be the statitics of the whole set of n regions.
+ *
+ * To reset the temporary data, one should call the Reset() function.
+ *
+ * To get the wanted values once the regions have been processed via the pipeline, use the Synthetize() method.
+ *
+ * \ingroup DiapOTBModule
+ */
+template<class TInputImage>
+class ITK_EXPORT PersistentMaximumMinimumImageFilter :
+  public PersistentImageFilter<TInputImage, TInputImage>
+{
+public:
+  /** Standard Self typedef */
+  typedef PersistentMaximumMinimumImageFilter                 Self;
+  typedef PersistentImageFilter<TInputImage, TInputImage> Superclass;
+  typedef itk::SmartPointer<Self>                         Pointer;
+  typedef itk::SmartPointer<const Self>                   ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Runtime information support. */
+  itkTypeMacro(PersistentMaximumMinimumImageFilter, PersistentImageFilter);
+
+  /** Image related typedefs. For Image Input*/
+  typedef TInputImage                   ImageType;
+  typedef typename TInputImage::Pointer InputImagePointer;
+
+  typedef typename TInputImage::RegionType   RegionType;
+  typedef typename TInputImage::SizeType     SizeType;
+  typedef typename TInputImage::IndexType    IndexType;
+  typedef typename TInputImage::PixelType    PixelType;
+  typedef double                             ValueType;
+  typedef typename ImageType::IndexValueType IndexValueType;
+  typedef typename ImageType::SizeValueType  SizeValueType;
+
+  itkStaticConstMacro(InputImageDimension, unsigned int,
+                      TInputImage::ImageDimension);
+
+  /** Image related typedefs. */
+  itkStaticConstMacro(ImageDimension, unsigned int,
+                      TInputImage::ImageDimension);
+
+  /** Type to use for computations. */
+  //  typedef typename itk::NumericTraits<PixelType>::RealType RealType;
+  typedef typename itk::NumericTraits<double>::RealType RealType;
+ 
+  /** Smart Pointer type to a DataObject. */
+  typedef typename itk::DataObject::Pointer DataObjectPointer;
+  typedef itk::ProcessObject::DataObjectPointerArraySizeType DataObjectPointerArraySizeType;
+
+  /** Type of DataObjects used for scalar outputs */
+  typedef itk::SimpleDataObjectDecorator<RealType>        RealObjectType;
+  typedef itk::SimpleDataObjectDecorator<long>            LongObjectType;
+  typedef itk::SimpleDataObjectDecorator<unsigned int>    UintObjectType;
+  typedef itk::SimpleDataObjectDecorator<PixelType>       PixelObjectType;
+  typedef itk::SimpleDataObjectDecorator<ValueType>       ValueObjectType;
+  typedef itk::SimpleDataObjectDecorator<IndexType>       IndexObjectType;
+
+    /** Return the number of valid points contained into the input grid. */
+  IndexType GetIndexOfMin() const
+  {
+    return this->GetIndexOfMinOutput()->Get();
+  }
+  IndexObjectType* GetIndexOfMinOutput();
+  const IndexObjectType* GetIndexOfMinOutput() const;
+
+  IndexType GetIndexOfMax() const
+  {
+    return this->GetIndexOfMaxOutput()->Get();
+  }
+  IndexObjectType* GetIndexOfMaxOutput();
+  const IndexObjectType* GetIndexOfMaxOutput() const;
+
+  /** Return the Minimum. */
+  ValueType GetMin() const
+  {
+    return this->GetMinOutput()->Get();
+  }
+  ValueObjectType* GetMinOutput();
+  const ValueObjectType* GetMinOutput() const;
+
+  /** Return the Maximum. */
+  ValueType GetMax() const
+  {
+    return this->GetMaxOutput()->Get();
+  }
+  ValueObjectType* GetMaxOutput();
+  const ValueObjectType* GetMaxOutput() const;
+
+  /** Make a DataObject of the correct type to be used as the specified
+   * output. */
+  DataObjectPointer MakeOutput(DataObjectPointerArraySizeType idx) ITK_OVERRIDE;
+  using Superclass::MakeOutput;
+
+  /**
+   * Synthetize and Reset function called by our PersistentFilterStreamingDecorator
+   */
+  void Synthetize(void) ITK_OVERRIDE;
+  void Reset(void) ITK_OVERRIDE;
+
+  itkSetMacro(IgnoreInfiniteValues, bool);
+  itkGetMacro(IgnoreInfiniteValues, bool);
+
+  itkSetMacro(IgnoreUserDefinedValue, bool);
+  itkGetMacro(IgnoreUserDefinedValue, bool);
+
+  itkSetMacro(UserIgnoredValue, RealType);
+  itkGetMacro(UserIgnoredValue, RealType);
+
+protected:
+  PersistentMaximumMinimumImageFilter();
+  ~PersistentMaximumMinimumImageFilter() ITK_OVERRIDE {}
+  void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE;
+
+  
+  /** PersistentMaximumMinimumImageFilter needs a larger input requested region than the output
+   * requested region.  As such, SARQuadraticAveragingImageFilter needs to provide an
+   * implementation for GenerateInputRequestedRegion() in order to inform the
+   * pipeline execution model.
+   * \sa ProcessObject::GenerateInputRequestedRegion() */
+  virtual void GenerateInputRequestedRegion() ITK_OVERRIDE;
+
+  /**
+   * OutputRegionToInputRegion returns the input region 
+   */
+  RegionType OutputRegionToInputRegion(const RegionType& outputRegion) const;
+
+  /** Multi-thread version GenerateData. */
+  void  ThreadedGenerateData(const RegionType&
+                             outputRegionForThread,
+                             itk::ThreadIdType threadId) ITK_OVERRIDE;
+
+  /** Pass the input through unmodified. Do this by Grafting in the
+   *  AllocateOutputs method.
+   */
+  void AllocateOutputs() ITK_OVERRIDE;
+  void GenerateOutputInformation() ITK_OVERRIDE;
+
+private:
+  PersistentMaximumMinimumImageFilter(const Self &); //purposely not implemented
+  void operator =(const Self&); //purposely not implemented
+
+  itk::Array<unsigned int>    m_ThreadIndexMaxC;
+  itk::Array<unsigned int>    m_ThreadIndexMaxL;
+  itk::Array<unsigned int>    m_ThreadIndexMinC;
+  itk::Array<unsigned int>    m_ThreadIndexMinL;
+  itk::Array<ValueType>       m_ThreadMax;
+  itk::Array<ValueType>       m_ThreadMin;
+;
+
+  /* Ignored values */
+  bool                        m_IgnoreInfiniteValues;
+  bool                        m_IgnoreUserDefinedValue;
+  RealType                    m_UserIgnoredValue;
+  std::vector<unsigned long>  m_IgnoredInfinitePixelCount;
+  std::vector<unsigned int>   m_IgnoredUserPixelCount;
+
+
+}; // end of class PersistentMaximumMinimumImageFilter
+
+/*===========================================================================*/
+
+/** \class SARStreamingMaximumMinimumImageFilter
+ * \brief This class streams the whole input image through the PersistentMaximumMinimumImageFilter.
+ *
+ * This way, it allows computing the first order global statistics of this image. It calls the
+ * Reset() method of the PersistentMaximumMinimumImageFilter before streaming the image and the
+ * Synthetize() method of the PersistentMaximumMinimumImageFilter after having streamed the image
+ * to compute the statistics. The accessor on the results are wrapping the accessors of the
+ * internal PersistentMaximumMinimumImageFilter.
+ * By default infinite values are ignored, use IgnoreInfiniteValues accessor to consider
+ * infinite values in the computation.
+ *
+ * This filter can be used as:
+ * \code
+ * typedef otb::StreamingMaximumMinimumImageFilter<ImageType> StatisticsType;
+ * StatisticsType::Pointer statistics = StatisticsType::New();
+ * statistics->SetInput(reader->GetOutput());
+ * statistics->Update();
+ * std::cout << statistics-> GetIndexOfMax() << std::endl;
+ * std::cout << statistics-> GetMax() << std::endl;
+ * \endcode
+ *
+ * \sa PersistentMaximumMinimumImageFilter
+ * \sa PersistentImageFilter
+ * \sa PersistentFilterStreamingDecorator
+ * \sa StreamingImageVirtualWriter
+ * \ingroup Streamed
+ * \ingroup Multithreaded
+ * \ingroup MathematicalStatisticsImageFilters
+ *
+ * \ingroup DiapOTBModule
+ */
+
+template<class TInputImage>
+class ITK_EXPORT SARStreamingMaximumMinimumImageFilter :
+  public PersistentFilterStreamingDecorator<PersistentMaximumMinimumImageFilter<TInputImage> >
+{
+public:
+  /** Standard Self typedef */
+  typedef SARStreamingMaximumMinimumImageFilter Self;
+  typedef PersistentFilterStreamingDecorator
+  <PersistentMaximumMinimumImageFilter<TInputImage> > Superclass;
+  typedef itk::SmartPointer<Self>       Pointer;
+  typedef itk::SmartPointer<const Self> ConstPointer;
+
+  /** Type macro */
+  itkNewMacro(Self);
+
+  /** Creation through object factory macro */
+  itkTypeMacro(StreamingMaximumMinimumImageFilter, PersistentFilterStreamingDecorator);
+
+  typedef typename Superclass::FilterType    StatFilterType;
+  typedef typename StatFilterType::PixelType PixelType;
+  typedef double ValueType;
+  typedef typename StatFilterType::RealType  RealType;
+  typedef TInputImage                        InputImageType;
+  typedef typename TInputImage::IndexType    IndexType;
+
+  /** Type of DataObjects used for scalar outputs */
+  typedef itk::SimpleDataObjectDecorator<RealType>  RealObjectType;
+  typedef itk::SimpleDataObjectDecorator<long>      LongObjectType;
+  typedef itk::SimpleDataObjectDecorator<PixelType> PixelObjectType;
+  typedef itk::SimpleDataObjectDecorator<ValueType> ValueObjectType;
+  typedef itk::SimpleDataObjectDecorator<IndexType> IndexObjectType;
+
+  using Superclass::SetInput;
+  void SetInput(InputImageType * input)
+  {
+    this->GetFilter()->SetInput(input);
+  }
+  const InputImageType * GetInput()
+  {
+    return this->GetFilter()->GetInput();
+  }
+
+  IndexType GetIndexOfMax()
+  {
+    return this->GetFilter()->GetIndexOfMaxOutput()->Get();
+  }
+
+  IndexType GetIndexOfMin()
+  {
+    return this->GetFilter()->GetIndexOfMinOutput()->Get();
+  }
+
+
+  ValueType GetMax()
+  {
+    return this->GetFilter()->GetMaxOutput()->Get();
+  }
+
+  ValueType GetMin()
+  {
+    return this->GetFilter()->GetMinOutput()->Get();
+  }
+
+
+  otbSetObjectMemberMacro(Filter, IgnoreInfiniteValues, bool);
+  otbGetObjectMemberMacro(Filter, IgnoreInfiniteValues, bool);
+
+  otbSetObjectMemberMacro(Filter, IgnoreUserDefinedValue, bool);
+  otbGetObjectMemberMacro(Filter, IgnoreUserDefinedValue, bool);
+
+  otbSetObjectMemberMacro(Filter, UserIgnoredValue, RealType);
+  otbGetObjectMemberMacro(Filter, UserIgnoredValue, RealType);
+
+protected:
+  /** Constructor */
+  SARStreamingMaximumMinimumImageFilter() {};
+  /** Destructor */
+  ~SARStreamingMaximumMinimumImageFilter() ITK_OVERRIDE {}
+
+private:
+  SARStreamingMaximumMinimumImageFilter(const Self &); //purposely not implemented
+  void operator =(const Self&); //purposely not implemented
+};
+
+} // end namespace otb
+
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbSARStreamingMaximumMinimumImageFilter.txx"
+#endif
+
+#endif
diff --git a/include/otbSARStreamingMaximumMinimumImageFilter.txx b/include/otbSARStreamingMaximumMinimumImageFilter.txx
new file mode 100644
index 0000000000000000000000000000000000000000..033d5393a49f72cbdbae23011e21f3618613b714
--- /dev/null
+++ b/include/otbSARStreamingMaximumMinimumImageFilter.txx
@@ -0,0 +1,410 @@
+/*
+ * Copyright (C) 2005-2018 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.
+ */
+
+#ifndef otbSARStreamingMaximumMinimumImageFilter_txx
+#define otbSARStreamingMaximumMinimumImageFilter_txx
+#include "otbSARStreamingMaximumMinimumImageFilter.h"
+
+#include "itkImageScanlineConstIterator.h"
+#include "itkImageRegionIterator.h"
+#include "itkProgressReporter.h"
+#include "otbMacro.h"
+
+#include <complex>
+
+namespace otb
+{
+
+template<class TInputImage>
+PersistentMaximumMinimumImageFilter<TInputImage>
+::PersistentMaximumMinimumImageFilter()
+  :m_ThreadMin(1),
+   m_ThreadMax(1),
+   m_ThreadIndexMaxC(0),
+   m_ThreadIndexMaxL(0),
+   m_ThreadIndexMinC(0),
+   m_ThreadIndexMinL(0),
+   m_IgnoreInfiniteValues(true),
+   m_IgnoreUserDefinedValue(false)
+{
+  //this->itk::ProcessObject::SetNumberOfRequiredOutputs(3);
+
+  // first output is a copy of the image, DataObject created by
+  // superclass
+  //
+  // allocate the data objects for the outputs which are
+  // just decorators around unsigned int types (for index)
+  typename IndexObjectType::Pointer output1
+    = static_cast<IndexObjectType*>(this->MakeOutput(3).GetPointer());
+  this->itk::ProcessObject::SetNthOutput(1, output1.GetPointer());
+   typename IndexObjectType::Pointer output2
+    = static_cast<IndexObjectType*>(this->MakeOutput(3).GetPointer());
+  this->itk::ProcessObject::SetNthOutput(2, output2.GetPointer());
+
+  // For Min/Max
+  typename ValueObjectType::Pointer output3
+    = static_cast<ValueObjectType*>(this->MakeOutput(1).GetPointer());
+  this->itk::ProcessObject::SetNthOutput(3, output3.GetPointer());
+  typename ValueObjectType::Pointer output4
+    = static_cast<ValueObjectType*>(this->MakeOutput(1).GetPointer());
+  this->itk::ProcessObject::SetNthOutput(4, output4.GetPointer());
+  
+  // Initialisation
+  IndexType indexInit;
+  indexInit[0] = 0;
+  indexInit[1] = 0;
+  this->GetIndexOfMinOutput()->Set(indexInit);
+  this->GetIndexOfMaxOutput()->Set(indexInit);
+  this->GetMinOutput()->Set(10E20);
+  this->GetMaxOutput()->Set(-10E20);
+
+  // Initiate the infinite ignored pixel counters
+  m_IgnoredInfinitePixelCount= std::vector<unsigned long>(this->GetNumberOfThreads(), 0);
+  m_IgnoredUserPixelCount= std::vector<unsigned int>(this->GetNumberOfThreads(), 0);
+
+  this->Reset();
+}
+
+template<class TInputImage>
+typename itk::DataObject::Pointer
+PersistentMaximumMinimumImageFilter<TInputImage>
+::MakeOutput(DataObjectPointerArraySizeType output)
+{
+  switch (output)
+    {
+    case 0:
+      return static_cast<itk::DataObject*>(LongObjectType::New().GetPointer());
+      break;
+    case 1:
+      return static_cast<itk::DataObject*>(ValueObjectType::New().GetPointer());
+      break;
+    case 2:
+      return static_cast<itk::DataObject*>(PixelObjectType::New().GetPointer());
+      break;
+    case 3:
+      return static_cast<itk::DataObject*>(IndexObjectType::New().GetPointer());
+      break;
+    default:
+      // might as well make an image
+      return static_cast<itk::DataObject*>(TInputImage::New().GetPointer());
+      break;
+    }
+}
+
+
+template<class TInputImage>
+typename PersistentMaximumMinimumImageFilter<TInputImage>::IndexObjectType*
+PersistentMaximumMinimumImageFilter<TInputImage>
+::GetIndexOfMinOutput()
+{
+  return static_cast<IndexObjectType*>(this->itk::ProcessObject::GetOutput(1));
+}
+
+template<class TInputImage>
+const typename PersistentMaximumMinimumImageFilter<TInputImage>::IndexObjectType*
+PersistentMaximumMinimumImageFilter<TInputImage>
+::GetIndexOfMinOutput() const
+{
+  return static_cast<const IndexObjectType*>(this->itk::ProcessObject::GetOutput(1));
+}
+
+template<class TInputImage>
+typename PersistentMaximumMinimumImageFilter<TInputImage>::IndexObjectType*
+PersistentMaximumMinimumImageFilter<TInputImage>
+::GetIndexOfMaxOutput()
+{
+  return static_cast<IndexObjectType*>(this->itk::ProcessObject::GetOutput(2));
+}
+
+template<class TInputImage>
+const typename PersistentMaximumMinimumImageFilter<TInputImage>::IndexObjectType*
+PersistentMaximumMinimumImageFilter<TInputImage>
+::GetIndexOfMaxOutput() const
+{
+  return static_cast<const IndexObjectType*>(this->itk::ProcessObject::GetOutput(2));
+}
+
+template<class TInputImage>
+typename PersistentMaximumMinimumImageFilter<TInputImage>::ValueObjectType*
+PersistentMaximumMinimumImageFilter<TInputImage>
+::GetMinOutput()
+{
+  return static_cast<ValueObjectType*>(this->itk::ProcessObject::GetOutput(3));
+}
+
+template<class TInputImage>
+const typename PersistentMaximumMinimumImageFilter<TInputImage>::ValueObjectType*
+PersistentMaximumMinimumImageFilter<TInputImage>
+::GetMinOutput() const
+{
+  return static_cast<const ValueObjectType*>(this->itk::ProcessObject::GetOutput(3));
+}
+
+
+template<class TInputImage>
+typename PersistentMaximumMinimumImageFilter<TInputImage>::ValueObjectType*
+PersistentMaximumMinimumImageFilter<TInputImage>
+::GetMaxOutput()
+{
+  return static_cast<ValueObjectType*>(this->itk::ProcessObject::GetOutput(4));
+}
+
+template<class TInputImage>
+const typename PersistentMaximumMinimumImageFilter<TInputImage>::ValueObjectType*
+PersistentMaximumMinimumImageFilter<TInputImage>
+::GetMaxOutput() const
+{
+  return static_cast<const ValueObjectType*>(this->itk::ProcessObject::GetOutput(4));
+}
+
+
+template<class TInputImage>
+void
+PersistentMaximumMinimumImageFilter<TInputImage>
+::GenerateOutputInformation()
+{
+  Superclass::GenerateOutputInformation();
+  if (this->GetInput())
+    {
+      this->GetOutput()->CopyInformation(this->GetInput());
+      this->GetOutput()->SetLargestPossibleRegion(this->GetInput()->GetLargestPossibleRegion());
+
+      if (this->GetOutput()->GetRequestedRegion().GetNumberOfPixels() == 0)
+	{
+	  this->GetOutput()->SetRequestedRegion(this->GetOutput()->GetLargestPossibleRegion());
+	}
+
+    }
+}
+template<class TInputImage>
+void
+PersistentMaximumMinimumImageFilter<TInputImage>
+::AllocateOutputs()
+{
+  // This is commented to prevent the streaming of the whole image for the first stream strip
+  // It shall not cause any problem because the output image of this filter is not intended to be used.
+  //InputImagePointer image = const_cast< TInputImage * >( this->GetInput() );
+  //this->GraftOutput( image );
+  // Nothing that needs to be allocated for the remaining outputs
+}
+
+template<class TInputImage>
+void
+PersistentMaximumMinimumImageFilter<TInputImage>
+::Synthetize()
+{
+  int numberOfThreads = this->GetNumberOfThreads();
+  
+  // Init indexes and values
+  IndexType minIndex, maxIndex;
+  minIndex = this->GetIndexOfMin();
+  maxIndex = this->GetIndexOfMax();;
+
+  ValueType minValue, maxValue;
+  minValue = this->GetMin();
+  maxValue = this->GetMax();
+  
+  // For each threads, get information into our Thread arrays
+  for (int i = 0; i < numberOfThreads; ++i)
+    {
+      // Conditions for min/max
+      if (minValue > m_ThreadMin[i])
+	{
+	  minValue = m_ThreadMin[i];
+	  minIndex[0] = m_ThreadIndexMinC[i];
+	  minIndex[1] = m_ThreadIndexMinL[i];
+	}
+      if (maxValue < m_ThreadMax[i])
+	{
+	  maxValue = m_ThreadMax[i];
+	  maxIndex[0] = m_ThreadIndexMaxC[i];
+	  maxIndex[1] = m_ThreadIndexMaxL[i];
+	}
+    }
+ 
+
+  // Set the outputs
+  this->GetIndexOfMinOutput()->Set(minIndex);
+  this->GetIndexOfMaxOutput()->Set(maxIndex);
+  this->GetMinOutput()->Set(minValue);
+  this->GetMaxOutput()->Set(maxValue);
+}
+
+template<class TInputImage>
+void
+PersistentMaximumMinimumImageFilter<TInputImage>
+::Reset()
+{
+  int numberOfThreads = this->GetNumberOfThreads();
+
+  // Resize the thread temporaries
+  m_ThreadIndexMaxC.SetSize(numberOfThreads);
+  m_ThreadIndexMaxL.SetSize(numberOfThreads);
+  m_ThreadIndexMinC.SetSize(numberOfThreads);
+  m_ThreadIndexMinL.SetSize(numberOfThreads);
+  m_ThreadMax.SetSize(numberOfThreads);
+  m_ThreadMin.SetSize(numberOfThreads);
+  // Initialize the temporaries
+  m_ThreadIndexMaxC.Fill(0);
+  m_ThreadIndexMaxL.Fill(0);
+  m_ThreadIndexMinC.Fill(0);
+  m_ThreadIndexMinL.Fill(0);
+  m_ThreadMin.Fill(10E20);
+  m_ThreadMax.Fill(-10E20);
+
+  if (m_IgnoreInfiniteValues)
+    {
+      m_IgnoredInfinitePixelCount= std::vector<unsigned long>(numberOfThreads, 0);
+    }
+
+  if (m_IgnoreUserDefinedValue)
+    {
+      m_IgnoredUserPixelCount= std::vector<unsigned int>(this->GetNumberOfThreads(), 0);
+    }
+}
+
+
+
+/** 
+ * Method OutputRegionToInputRegion for GenerateInputRequestedRegion
+ */
+template<class TInputImage >
+typename PersistentMaximumMinimumImageFilter< TInputImage >::RegionType 
+PersistentMaximumMinimumImageFilter< TInputImage >
+::OutputRegionToInputRegion(const RegionType& outputRegion) const
+{
+  // Compute the input requested region (size and start index)
+  // Use the image transformations to insure an input requested region
+  // that will provide the proper range
+  const SizeType & outputRequestedRegionSize = outputRegion.GetSize();
+  const IndexType & outputRequestedRegionIndex = outputRegion.GetIndex();
+
+  // Compute input index 
+  IndexType  inputRequestedRegionIndex = outputRequestedRegionIndex;
+
+  // Compute input size
+  SizeType inputRequestedRegionSize = outputRequestedRegionSize; 
+ 
+  // Input region
+  RegionType inputRequestedRegion = outputRegion;
+  inputRequestedRegion.SetIndex(inputRequestedRegionIndex);
+  inputRequestedRegion.SetSize(inputRequestedRegionSize);
+
+  return inputRequestedRegion;  
+}
+/** 
+ * Method OutputRegionToInputRegion
+ */
+template<class TInputImage>
+void
+PersistentMaximumMinimumImageFilter< TInputImage >
+::GenerateInputRequestedRegion()
+{
+  RegionType outputRequestedRegion = this->GetOutput()->GetRequestedRegion();
+  RegionType inputRequestedRegion = OutputRegionToInputRegion(outputRequestedRegion);
+
+  InputImagePointer  inputPtr = const_cast< ImageType * >( this->GetInput() );
+  
+  inputPtr->SetRequestedRegion(inputRequestedRegion);
+}
+
+
+
+template<class TInputImage>
+void
+PersistentMaximumMinimumImageFilter<TInputImage>
+::ThreadedGenerateData(const RegionType& outputRegionForThread,
+                       itk::ThreadIdType threadId)
+{ 
+  // Grab the input
+  InputImagePointer inputPtr =  const_cast<TInputImage *>(this->GetInput(0));
+  // Compute corresponding input region
+  RegionType inputRegionForThread = OutputRegionToInputRegion(outputRegionForThread);
+
+  // support progress methods/callbacks
+  itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
+
+  //  Define/declare an iterator that will walk the input region for this
+  // thread. 
+  typedef itk::ImageScanlineConstIterator< ImageType > InputIterator;
+  InputIterator  inIt(this->GetInput(), inputRegionForThread);
+  
+  inIt.GoToBegin();
+  
+  ValueType valueCurrent;
+ 
+  // For each line 
+  while ( !inIt.IsAtEnd())
+  {
+    inIt.GoToBeginOfLine();
+
+    // For each column
+    while (!inIt.IsAtEndOfLine())
+    {
+      //The input image value
+      valueCurrent= inIt.Get();
+            
+      bool valueCurrentIsFinite = (vnl_math_isfinite(valueCurrent));
+      
+      // Assigne if finite
+       if (valueCurrentIsFinite)
+	 {
+	   // Conditions for min/max
+	   if (m_ThreadMin[threadId] > valueCurrent)
+	     {
+	       m_ThreadMin[threadId] = valueCurrent;
+	       m_ThreadIndexMinC[threadId] = inIt.GetIndex()[0];
+	       m_ThreadIndexMinL[threadId] = inIt.GetIndex()[1];
+	     }
+	   if (m_ThreadMax[threadId] < valueCurrent)
+	     {
+	       m_ThreadMax[threadId] = valueCurrent;
+	       m_ThreadIndexMaxC[threadId] = inIt.GetIndex()[0];
+	       m_ThreadIndexMaxL[threadId] = inIt.GetIndex()[1];
+	     }
+	 }
+       
+     
+       // Next colunm
+       ++inIt;
+    }
+     // Next Line
+    inIt.NextLine();
+    
+  }
+
+}
+
+template <class TInputImage>
+void
+PersistentMaximumMinimumImageFilter<TInputImage>
+::PrintSelf(std::ostream& os, itk::Indent indent) const
+{
+  Superclass::PrintSelf(os, indent);
+
+  os << indent << "Max: "
+     << static_cast<typename itk::NumericTraits<ValueType>::PrintType>(this->GetMax()) << std::endl;
+  os << indent << "Min: "
+     << static_cast<typename itk::NumericTraits<ValueType>::PrintType>(this->GetMin()) << std::endl;
+  os << indent << "Index of Max: "      << this->GetIndexOfMax() << std::endl;
+  os << indent << "Index of Min: "      << this->GetIndexOfMin() << std::endl;
+}
+} // end namespace otb
+#endif
diff --git a/json_schemas/schema_MultiSlc.json b/json_schemas/schema_MultiSlc.json
index 45a21150d10e9eb5dad27fba1e8521a78eed6c45..94b232ea36e02c7f9a9fa7d94d1e244b8b5d7676 100644
--- a/json_schemas/schema_MultiSlc.json
+++ b/json_schemas/schema_MultiSlc.json
@@ -118,6 +118,8 @@
 				   "Grid_Threshold": {"type": "number"},
 				   "Grid_Gap": {"type": "number"},
 				   "Interferogram_gain": {"type": "number"},
+				   "Interferogram_mlran": {"type": "number"},
+				   "Interferogram_mlazi": {"type": "number"},
 				   "Activate_Interferogram": {"type": "string", "default": "yes"},
 				   "Activate_Ortho": {"type": "string"},
 				   "Spacingxy": {"type": "number", "default": 0.0001},
diff --git a/json_schemas/schema_S1SM.json b/json_schemas/schema_S1SM.json
index e649de737ca723bdd7e2df4b51ef9368f8c5f792..2df1353ed431bb844abf14fccec2ab69e3c2ece2 100644
--- a/json_schemas/schema_S1SM.json
+++ b/json_schemas/schema_S1SM.json
@@ -29,7 +29,7 @@
 		    "required": ["output_dir"],
 		    "additionalProperties": false,
 		    "properties": {"output_dir": {"type": "string"}}
-		}
+		},
 		"sensor": 
 		{
 		    "type": "object",
@@ -113,6 +113,8 @@
 				   "Grid_Threshold": {"type": "number"},
 				   "Grid_Gap": {"type": "number"},
 				   "Interferogram_gain": {"type": "number"},
+				   "Interferogram_mlran": {"type": "number"},
+		                   "Interferogram_mlazi": {"type": "number"},
 				   "Interferogram_ortho": {"type": "boolean"}
 				  }
 		}
diff --git a/python_src/SAR_MultiSlc.py b/python_src/SAR_MultiSlc.py
index 891372296b77f8d89a7fdb88e3470763d7fa8fd8..fe7d6c901795ba4986d1fe3b43df854aa6733efa 100644
--- a/python_src/SAR_MultiSlc.py
+++ b/python_src/SAR_MultiSlc.py
@@ -182,10 +182,26 @@ if __name__ == "__main__":
     ml_geoGrid_azimut = ml_azimut
     gain_interfero = dict_DInSAR['parameter']['Interferogram_gain']
 
+    ml_interf_range = ml_range
+    ml_interf_azimut = ml_azimut
+    
+    if "Interferogram_mlran" in dict_DInSAR['parameter'] :
+        ml_interf_range = int(dict_DInSAR['parameter']['Interferogram_mlran'])
+    
+    if "Interferogram_mlazi" in dict_DInSAR['parameter'] :
+        ml_interf_azimut = int(dict_DInSAR['parameter']['Interferogram_mlazi'])
+
+
     if (geoGrid_threshold < 0) or (geoGrid_threshold > 1):
         func_utils.log(logging.CRITICAL, "Error, Wrong Threshold for fine deformation grid")
         geoGrid_threshold = 0.3
 
+    # ====== Check if interferogram is activated for ortho interferogram
+    if ortho_interferogram == "yes" and version_interferogram == "no":
+        func_utils.log(logging.CRITICAL, "Error, Impossible to have ortho interferogram without interferogram\n"
+        "If Ortho is required, please activate interferogram estimation in your json file")
+        quit()
+
     # ====== Check if images exist
     func_utils.check_ifExist(srtm_shapefile)
     func_utils.check_ifExist(hgts_path)
@@ -247,11 +263,33 @@ if __name__ == "__main__":
     func_utils.log(logging.INFO, "ml_geoGrid_range : {param}".format(param=ml_geoGrid_range))
     func_utils.log(logging.INFO, "ml_geoGrid_azimut : {param}".format(param=ml_geoGrid_azimut))
     func_utils.log(logging.INFO, "gain_interfero : {param}".format(param=gain_interfero))
+    func_utils.log(logging.INFO, "ml_interf_range : {param}".format(param=ml_interf_range))
+    func_utils.log(logging.INFO, "ml_interf_azimut : {param}".format(param=ml_interf_azimut))
     func_utils.log(logging.INFO, "Spacingxy : {param}".format(param=spacingxy))
     func_utils.log(logging.INFO, "roi : {param}".format(param=roi))
     func_utils.log(logging.INFO, "Activate_Interferogram : {param}".format(param=version_interferogram))
     func_utils.log(logging.INFO, "Activate_Ortho : {param}".format(param=ortho_interferogram))
 
+
+    # Retrieve some information about our master image
+    dictKWLMaster = func_utils.getImageKWL(master_Image)
+    number_col = int(dictKWLMaster['number_samples'])
+    number_lines = int(dictKWLMaster['number_lines'])
+    
+    # Check input size (Master size) to protect memory. 
+    if (number_col > 15000 or number_lines > 15000) :
+        
+        intermediate_mlran = int(number_col/15000) + 1
+        intermediate_mlazi = int(number_lines/15000) + 1
+        
+        # Compare ml factor with intermediate
+        if ((intermediate_mlazi*intermediate_mlran) > (ml_range*ml_azimut)) :
+            func_utils.log(logging.CRITICAL, "ML Factors are not appropriate (too low) for these estimations. Please use other factors such as : {iran} x {iazi} \n".format(iran=intermediate_mlran, iazi=intermediate_mlazi))
+    
+            quit()
+
+
+    
     # =============================
     # Get the elements from os.dirs
     # =============================
@@ -452,6 +490,8 @@ if __name__ == "__main__":
         param['ml_range'] = ml_range
         param['ml_geoGrid_azimut'] = ml_geoGrid_azimut
         param['ml_geoGrid_range'] = ml_geoGrid_range
+        param['ml_interf_range'] = ml_interf_range  
+        param['ml_interf_azimut'] = ml_interf_azimut
         param['geoGrid_gridstep_range'] = geoGrid_gridstep_range
         param['geoGrid_gridstep_azimut'] = geoGrid_gridstep_azimut
         param['geoGrid_threshold'] = geoGrid_threshold
@@ -474,7 +514,9 @@ if __name__ == "__main__":
 
         list_of_Grids, list_of_Interferogram = DInSar.gridToInterferogram(dem, master_Image, master_Image_base, slave_Image, slave_Image_base, master_data_dir, output_dir, param, 'Others', output_dir)
 
-        interferogram_path = list_of_Interferogram[0]
+        interferogram_path = ""
+        if version_interferogram == "yes":
+            interferogram_path = list_of_Interferogram[0]
         grid_path = list_of_Grids[0]
 
         # ==================================== #
@@ -530,16 +572,16 @@ if __name__ == "__main__":
                 interf_roi = "interferogram_roi.tif"
                 func_utils.extract_roi(os.path.join(output_dir, interf_ortho), os.path.join(output_dir, interf_roi), roi)
                 func_utils.extract_band123(os.path.join(output_dir, interf_roi), os.path.join(output_dir, Interfero_roi))
-        if ortho_interferogram == "no" and roi is None:
+        if version_interferogram == "yes" and ortho_interferogram == "no" and roi is None:
             func_utils.extract_band123(interferogram_path, os.path.join(output_dir, InterferoB123))
 
          # ==================================== #
           #               Removing             # 
            #               files              #
             # ============================== #
-
-        func_utils.silentremove(os.path.dirname(interferogram_path), os.path.basename(interferogram_path))
-        func_utils.silentremove(os.path.dirname(interferogram_path), os.path.basename(interferogram_path).split(".")[0]+".geom")
+        if version_interferogram == "yes":
+            func_utils.silentremove(os.path.dirname(interferogram_path), os.path.basename(interferogram_path))
+            func_utils.silentremove(os.path.dirname(interferogram_path), os.path.basename(interferogram_path).split(".")[0]+".geom")
         if ortho_interferogram == "yes":
             interferogram_ortho = "interferogram_ortho.tif"
             func_utils.silentremove(output_dir, interferogram_ortho)
diff --git a/python_src/SAR_MultiSlc_IW.py b/python_src/SAR_MultiSlc_IW.py
index 68b73c0bdaad3f643324cf6756beaee69936ab74..fee8b494dd02ac5d03456a6794c063f22534cdc0 100644
--- a/python_src/SAR_MultiSlc_IW.py
+++ b/python_src/SAR_MultiSlc_IW.py
@@ -178,6 +178,12 @@ if __name__ == "__main__":
         esd_AutoMode = True
         esd_NbIter = 10 # 10 iterations maximum for automatic mode
 
+    # ====== Check if interferogram is activated for ortho interferogram
+    if ortho_interferogram == "yes" and version_interferogram == "no":
+        func_utils.log(logging.CRITICAL, "Error, Impossible to have ortho interferogram without interferogram\n"
+        "If Ortho is required, please activate interferogram estimation in your json file")
+        quit()
+
     # ====== Check Threshold
     if (geoGrid_threshold < 0) or (geoGrid_threshold > 1) :
         func_utils.log(logging.CRITICAL, "Error, Wrong Threshold for fine deformation grid")
diff --git a/python_src/diapOTB.py b/python_src/diapOTB.py
index 2a562a8a71a8d1579dde54e37a723ee54bccea2b..6ce3e15503823b7821aaa13f3a5a10aa559c0f60 100644
--- a/python_src/diapOTB.py
+++ b/python_src/diapOTB.py
@@ -83,8 +83,8 @@ if __name__ == "__main__":
         mode = dict_Global['sensor']['mode']
 
     # Pre_Processing
-    ml_range = dict_PreProcessing['parameter']['ML_range'] 
-    ml_azimut = dict_PreProcessing['parameter']['ML_azimut']
+    ml_range = int(dict_PreProcessing['parameter']['ML_range']) 
+    ml_azimut = int(dict_PreProcessing['parameter']['ML_azimut'])
     ml_gain = dict_PreProcessing['parameter']['ML_gain']
     dop_file = dict_PreProcessing['out']['doppler_file']
 
@@ -107,7 +107,17 @@ if __name__ == "__main__":
     ml_geoGrid_range = ml_range
     ml_geoGrid_azimut = ml_azimut
     gain_interfero = dict_DInSAR['parameter']['Interferogram_gain']
+
+    ml_interf_range = ml_range
+    ml_interf_azimut = ml_azimut
+    
+    if "Interferogram_mlran" in dict_DInSAR['parameter'] :
+        ml_interf_range = int(dict_DInSAR['parameter']['Interferogram_mlran'])
     
+    if "Interferogram_mlazi" in dict_DInSAR['parameter'] :
+        ml_interf_azimut = int(dict_DInSAR['parameter']['Interferogram_mlazi'])
+
+
     if (geoGrid_threshold < 0) or (geoGrid_threshold > 1) :
         func_utils.log(logging.CRITICAL, "Error, Wrong Threshold for fine deformation grid")
 
@@ -162,7 +172,10 @@ if __name__ == "__main__":
     func_utils.log(logging.INFO, "ml_geoGrid_range : {param}".format(param=ml_geoGrid_range))
     func_utils.log(logging.INFO, "ml_geoGrid_azimut : {param}".format(param=ml_geoGrid_azimut))
     func_utils.log(logging.INFO, "gain_interfero : {param}".format(param=gain_interfero))
-    
+    func_utils.log(logging.INFO, "ml_interf_range : {param}".format(param=ml_interf_range))
+    func_utils.log(logging.INFO, "ml_interf_azimut : {param}".format(param=ml_interf_azimut))
+    func_utils.log(logging.INFO, "ml_geoGrid_azimut : {param}".format(param=ml_geoGrid_azimut))
+
 
     func_utils.log(logging.INFO, "########### Input Images for the current execution ############## ")
         
@@ -226,7 +239,24 @@ if __name__ == "__main__":
     func_utils.log(logging.INFO, "slave_Image = {img}".format(img=slave_Image))
     func_utils.log(logging.INFO, "dem : {param}".format(param=dem))
 
-
+    # Retrieve some information about our master image
+    dictKWLMaster = func_utils.getImageKWL(master_Image)
+    number_col = int(dictKWLMaster['number_samples'])
+    number_lines = int(dictKWLMaster['number_lines'])
+    
+    # Check input size (Master size) to protect memory. 
+    if (number_col > 15000 or number_lines > 15000) :
+        
+        intermediate_mlran = int(number_col/15000) + 1
+        intermediate_mlazi = int(number_lines/15000) + 1
+        
+        # Compare ml factor with intermediate
+        if ((intermediate_mlazi*intermediate_mlran) > (ml_range*ml_azimut)) :
+            func_utils.log(logging.CRITICAL, "ML Factors are not appropriate (too low) for these estimations. Please use other factors such as : {iran} x {iazi} \n".format(iran=intermediate_mlran, iazi=intermediate_mlazi))
+    
+            quit()
+        
+        
     func_utils.printOnStd("\n Beginning of DiapOTB processing (S1 SM or Cosmo mode) \n")
     func_utils.log(logging.INFO, "############ Beginning of DiapOTB processing (S1 SM or Cosmo mode) ##############")
 
@@ -316,6 +346,8 @@ if __name__ == "__main__":
     param['ml_range'] = ml_range
     param['ml_geoGrid_azimut'] = ml_geoGrid_azimut
     param['ml_geoGrid_range'] = ml_geoGrid_range
+    param['ml_interf_range'] = ml_interf_range  
+    param['ml_interf_azimut'] = ml_interf_azimut
     param['geoGrid_gridstep_range'] = geoGrid_gridstep_range
     param['geoGrid_gridstep_azimut'] = geoGrid_gridstep_azimut
     param['geoGrid_threshold'] = geoGrid_threshold
diff --git a/python_src/processings/DInSar.py b/python_src/processings/DInSar.py
index 124246d3c8217ffd2565e5d404fdee76d5ea8723..a73fc76f5ba7fb5d664460dcdcc25091e995b54e 100644
--- a/python_src/processings/DInSar.py
+++ b/python_src/processings/DInSar.py
@@ -265,6 +265,16 @@ def gridToInterferogram_Others(dem, master_Image, master_Image_base, slave_Image
     ml_range = param['ml_range']
     ml_geoGrid_azimut = param['ml_geoGrid_azimut']
     ml_geoGrid_range = param['ml_geoGrid_range']
+    
+    ml_interf_range = ml_range
+    if "ml_interf_range" in param :
+        ml_interf_range = param['ml_interf_range']
+    
+    ml_interf_azimut = ml_azimut
+    if "ml_interf_azimut" in param :
+        ml_interf_azimut = param['ml_interf_azimut']
+    
+
     geoGrid_gridstep_range = param['geoGrid_gridstep_range']
     geoGrid_gridstep_azimut = param['geoGrid_gridstep_azimut']    
     geoGrid_threshold = param['geoGrid_threshold']
@@ -292,7 +302,7 @@ def gridToInterferogram_Others(dem, master_Image, master_Image_base, slave_Image
 
     derampApp = partial(diapOTBApp.deramp, gridsteprange=geoGrid_gridstep_range, gridstepazimut=geoGrid_gridstep_azimut, reramp="true", shift="true")
 
-    interferogramApp = partial(diapOTBApp.interferogram, gridsteprange=geoGrid_gridstep_range, gridstepazimut=geoGrid_gridstep_azimut, mlran=ml_range, mlazi=ml_azimut, gain=gain_interfero)
+    interferogramApp = partial(diapOTBApp.interferogram, gridsteprange=geoGrid_gridstep_range, gridstepazimut=geoGrid_gridstep_azimut, mlran=ml_interf_range, mlazi=ml_interf_azimut, gain=gain_interfero)
         
 
     # Empty list