Commit 38a331b7 authored by Julien Osman's avatar Julien Osman

Merge branch 'improve_qgis_parameter_integration' into 'develop'

Improve qgis parameter integration

See merge request !768
parents 6e85bdc9 b52c66bb
Pipeline #6516 passed with stages
in 102 minutes and 33 seconds
......@@ -25,7 +25,7 @@ import argparse
import re
import otbApplication
from otbApplication import ParameterType_Bool, ParameterType_Int, ParameterType_Radius, ParameterType_RAM, ParameterType_Float, ParameterType_String, ParameterType_StringList, ParameterType_InputFilename, ParameterType_OutputFilename, ParameterType_InputImage, ParameterType_OutputImage, ParameterType_InputVectorData, ParameterType_OutputVectorData, ParameterType_Directory, ParameterType_Choice, ParameterType_InputImageList, ParameterType_InputVectorDataList, ParameterType_InputFilenameList, ParameterType_ListView, ParameterType_Group
from otbApplication import ParameterType_Bool, ParameterType_Int, ParameterType_Radius, ParameterType_RAM, ParameterType_Float, ParameterType_String, ParameterType_StringList, ParameterType_InputFilename, ParameterType_OutputFilename, ParameterType_InputImage, ParameterType_OutputImage, ParameterType_InputVectorData, ParameterType_OutputVectorData, ParameterType_Directory, ParameterType_Choice, ParameterType_InputImageList, ParameterType_InputVectorDataList, ParameterType_InputFilenameList, ParameterType_ListView, ParameterType_Band, ParameterType_Field, ParameterType_Group
from otb_warnings import application_documentation_warnings
......@@ -82,7 +82,7 @@ def GetApplicationExamplePythonSnippet(app,idx,expand = False, inputpath="",outp
value = app.GetExampleParameterValue(idx,i)
paramtype = app.GetParameterType(param)
paramrole = app.GetParameterRole(param)
if paramtype == ParameterType_ListView:
if paramtype == ParameterType_ListView or paramtype == ParameterType_Band or paramtype == ParameterType_Field:
if app.GetListViewSingleSelectionMode(param):
output += "\t" + appname + ".SetParameterString("+EncloseString(param)+", "+EncloseString(value)+")"
else:
......@@ -182,8 +182,8 @@ def rst_parameter_value(app, key):
type = app.GetParameterType(key)
# ListView is a special case depending on its mode
if type == ParameterType_ListView:
# ListView/Band/Field is a special case depending on its mode
if type == ParameterType_ListView or type == ParameterType_Band or type == ParameterType_Field:
if app.GetListViewSingleSelectionMode(key):
return "string"
else:
......
......@@ -169,6 +169,12 @@ parameters:
- ``ParameterType_RAM`` : parameter storing the maximum amount of RAM
to be used.
- ``ParameterType_Field`` : parameter storing a list of field from a given
vector data (support multi-choice and single-choice).
- ``ParameterType_Band`` : parameter storing a list of band from a given
raster data (support multi-choice and single-choice).
Parameters description
~~~~~~~~~~~~~~~~~~~~~~
......
QGIS interface
==============
OTB Applications are fully integrated in QGIS since QGIS 3.8.
You can configure OTB for QGIS according to the:
OTB Applications are fully integrated in QGIS since QGIS 3.8.
You can configure OTB for QGIS according to the:
- `QGIS Provider documentation for latest LTR <https://docs.qgis.org/latest/en/docs/user_manual/processing/3rdParty.html>`_.
- `QGIS Provider documentation <https://docs.qgis.org/testing/en/docs/user_manual/processing/3rdParty.html>`_.
......@@ -16,37 +16,41 @@ for the binary packages of OTB 7.1 and above. In this case QGIS 3.14 or more sho
The table below summarizes which version of OTB can be used with which version of QGIS.
+---------------+-----------------+--------------------+
| | QGIS 3.8 - 3.12 | QGIS 3.14 and more |
+---------------+-----------------+--------------------+
| OTB 6.6.1 | Compatible | Compatible |
+---------------+-----------------+--------------------+
| OTB 7.0.0 | Compatible | Compatible |
+---------------+-----------------+--------------------+
| OTB 7.1.0 | Not Compatible | Compatible |
+---------------+-----------------+--------------------+
+---------------+-----------------+-----------------+-----------------+
| | QGIS 3.8 - 3.12 | QGIS 3.14 | QGIS 3.16 |
+---------------+-----------------+-----------------+-----------------+
| OTB 6.6.1 | Compatible | Compatible | Compatible |
+---------------+-----------------+-----------------+-----------------+
| OTB 7.0.0 | Compatible | Compatible | Compatible |
+---------------+-----------------+-----------------+-----------------+
| OTB 7.1.0 | Not Compatible | Compatible | Compatible |
+---------------+-----------------+-----------------+-----------------+
| OTB 7.2.0 | Not Compatible | Compatible | Compatible |
+---------------+-----------------+-----------------+-----------------+
| OTB 8.0.0 | Not Compatible | Not Compatible | Compatible |
+---------------+-----------------+-----------------+-----------------+
Use OTB in old QGIS version (3.6 and less)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. warning:: Please consider upgrading your QGIS version.
Since QGIS 3.8 and with 3.10 LTR version, the configuration of OTB Application is
Since QGIS 3.8 and with 3.10 LTR version, the configuration of OTB Application is
directly done in QGIS Provider (see above).
If you use older version of QGIS (from 3.2 to 3.6), you need to install an
additional plugin in order to use OTB applications. This plugin is available
`here <https://gitlab.orfeo-toolbox.org/orfeotoolbox/qgis-otb-plugin>`_
If you use older version of QGIS (from 3.2 to 3.6), you need to install an
additional plugin in order to use OTB applications. This plugin is available
`here <https://gitlab.orfeo-toolbox.org/orfeotoolbox/qgis-otb-plugin>`_
with specific installation instructions.
Troubleshooting
^^^^^^^^^^^^^^^
As of QGIS 3.8 the OTB plugin is in the core. It might get messy if you
have a previously installed plugin. Try to remove the old plugin before
As of QGIS 3.8 the OTB plugin is in the core. It might get messy if you
have a previously installed plugin. Try to remove the old plugin before
launching QGIS.
Issue tracking
^^^^^^^^^^^^^^
If you encounter issues with integration of OTB application into QGIS,
If you encounter issues with integration of OTB application into QGIS,
please `fill an issue <https://gitlab.orfeo-toolbox.org/orfeotoolbox/otb/-/issues/new?issue[assignee_id]=&issue[milestone_id]=>`_ into the OTB issue tracker with `qgis` label.
......@@ -133,11 +133,13 @@ private:
AddParameter(ParameterType_InputImage, "ref.raster.in", "Input reference image");
SetParameterDescription("ref.raster.in", "Input image containing the ground truth labels");
AddParameter(ParameterType_InputFilename, "ref.vector.in", "Input reference vector data");
AddParameter(ParameterType_InputVectorData, "ref.vector.in", "Input reference vector data");
SetParameterDescription("ref.vector.in", "Input vector data of the ground truth");
AddParameter(ParameterType_ListView, "ref.vector.field", "Field name");
AddParameter(ParameterType_Field, "ref.vector.field", "Field name");
SetParameterDescription("ref.vector.field", "Field name containing the label values");
SetVectorData("ref.vector.field", "ref.vector.in");
SetTypeFilter("ref.vector.field", { OFTString, OFTInteger, OFTInteger64 });
SetListViewSingleSelectionMode("ref.vector.field", true);
AddParameter(ParameterType_Int, "ref.raster.nodata", "Value for nodata pixels in the reference raster");
......@@ -186,6 +188,7 @@ private:
ClearChoices("ref.vector.field");
FieldParameter::TypeFilterType typeFilter = GetTypeFilter("ref.vector.field");
for (int iField = 0; iField < feature.ogr().GetFieldCount(); iField++)
{
std::string key, item = feature.ogr().GetFieldDefnRef(iField)->GetNameRef();
......@@ -195,7 +198,7 @@ private:
OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(iField)->GetType();
if (fieldType == OFTString || fieldType == OFTInteger || fieldType == OFTInteger64)
if (typeFilter.empty() || std::find(typeFilter.begin(), typeFilter.end(), fieldType) != std::end(typeFilter))
{
std::string tmpKey = "ref.vector.field." + key.substr(0, end - key.begin());
AddChoice(tmpKey, item);
......
......@@ -63,8 +63,9 @@ private:
AddParameter(ParameterType_OutputFilename, "outstats", "Output XML file");
SetParameterDescription("outstats", "XML file containing mean and variance of each feature.");
AddParameter(ParameterType_ListView, "feat", "Feature");
AddParameter(ParameterType_Field, "feat", "Feature");
SetParameterDescription("feat", "List of features to consider for statistics.");
SetVectorData("feat", "inshp");
// Doc example parameter settings
SetDocExampleParameterValue("inshp", "vectorData.shp");
......
......@@ -75,9 +75,9 @@ private:
AddParameter(ParameterType_OutputFilename, "insvm", "Input model filename");
SetParameterDescription("insvm", "Input model filename.");
AddParameter(ParameterType_ListView, "feat", "Features");
AddParameter(ParameterType_Field, "feat", "Features");
SetParameterDescription("feat", "Features to be calculated");
SetVectorData("feat","inshp");
AddParameter(ParameterType_String, "cfield", "Field containing the predicted class");
SetParameterDescription("cfield", "Field containing the predicted class");
......
......@@ -50,7 +50,7 @@ void VectorClassifier::DoInitSpecialization()
SetDocSeeAlso("TrainVectorClassifier");
AddDocTag(Tags::Learning);
AddParameter(ParameterType_InputFilename, "in", "Name of the input vector data");
AddParameter(ParameterType_InputVectorData, "in", "Name of the input vector data");
SetParameterDescription("in", "The input vector data file to classify.");
AddParameter(ParameterType_InputFilename, "instat", "Statistics file");
......@@ -70,10 +70,12 @@ void VectorClassifier::DoInitSpecialization()
"Caution, the 'cfield' must not exist in the input file if you are updating the file.");
SetParameterString("cfield", "predicted");
AddParameter(ParameterType_ListView, "feat", "Field names to be calculated");
AddParameter(ParameterType_Field, "feat", "Field names to be calculated");
SetParameterDescription("feat",
"List of field names in the input vector data used as features for training. "
"Put the same field names as the TrainVectorClassifier application.");
SetVectorData("feat", "in");
SetTypeFilter("feat", {OFTInteger, OFTInteger64, OFTReal});
AddParameter(ParameterType_Bool, "confmap", "Confidence map");
SetParameterDescription("confmap",
......
......@@ -49,7 +49,7 @@ void VectorRegression::DoInitSpecialization()
SetDocSeeAlso("TrainVectorRegression");
AddDocTag(Tags::Learning);
AddParameter(ParameterType_InputFilename, "in", "Name of the input vector data");
AddParameter(ParameterType_InputVectorData, "in", "Name of the input vector data");
SetParameterDescription("in", "The input vector data file to classify.");
AddParameter(ParameterType_InputFilename, "instat", "Statistics file");
......@@ -69,10 +69,12 @@ void VectorRegression::DoInitSpecialization()
"Caution, the 'cfield' must not exist in the input file if you are updating the file.");
SetParameterString("cfield", "predicted");
AddParameter(ParameterType_ListView, "feat", "Field names to be calculated");
AddParameter(ParameterType_Field, "feat", "Field names to be calculated");
SetParameterDescription("feat",
"List of field names in the input vector data used as features for training. "
"Put the same field names as the TrainVectorRegression application.");
SetVectorData("feat", "in");
SetTypeFilter("feat", {OFTInteger, OFTInteger64, OFTReal});
AddParameter(ParameterType_OutputFilename, "out", "Output vector data file");
MandatoryOff("out");
......
......@@ -55,6 +55,7 @@ void VectorPrediction<RegressionMode>::DoUpdateParameters()
ClearChoices("feat");
FieldParameter::TypeFilterType typeFilter = GetTypeFilter("feat");
for (int iField = 0; iField < layerDefn.GetFieldCount(); iField++)
{
auto fieldDefn = layerDefn.GetFieldDefn(iField);
......@@ -63,7 +64,8 @@ void VectorPrediction<RegressionMode>::DoUpdateParameters()
key.erase(std::remove_if(key.begin(), key.end(), [](char c) { return !std::isalnum(c); }), key.end());
std::transform(key.begin(), key.end(), key.begin(), tolower);
auto fieldType = fieldDefn->GetType();
if (fieldType == OFTInteger || fieldType == OFTInteger64 || fieldType == OFTReal)
if (typeFilter.empty() || std::find(typeFilter.begin(), typeFilter.end(), fieldType) != std::end(typeFilter))
{
std::string tmpKey = "feat." + key;
AddChoice(tmpKey, item);
......
......@@ -97,8 +97,9 @@ private:
MandatoryOff("io.stats");
SetParameterDescription("io.stats", "XML file containing mean and variance of each feature.");
AddParameter(ParameterType_StringList, "feat", "Field names to be used for training");
AddParameter(ParameterType_Field, "feat", "Field names to be used for training");
SetParameterDescription("feat", "List of field names in the input vector data used as features for training.");
SetVectorData("feat", "io.vd");
Superclass::DoInit();
......@@ -121,6 +122,33 @@ private:
void DoUpdateParameters() override
{
if (HasValue("io.vd"))
{
auto shapefileName = GetParameterString("io.vd");
auto ogrDS = otb::ogr::DataSource::New(shapefileName, otb::ogr::DataSource::Modes::Read);
auto layer = ogrDS->GetLayer(0);
OGRFeatureDefn& layerDefn = layer.GetLayerDefn();
ClearChoices("feat");
FieldParameter::TypeFilterType typeFilter = GetTypeFilter("feat");
for (int iField = 0; iField < layerDefn.GetFieldCount(); iField++)
{
auto fieldDefn = layerDefn.GetFieldDefn(iField);
std::string item = fieldDefn->GetNameRef();
std::string key(item);
key.erase(std::remove_if(key.begin(), key.end(), [](char c) { return !std::isalnum(c); }), key.end());
std::transform(key.begin(), key.end(), key.begin(), tolower);
auto fieldType = fieldDefn->GetType();
if (typeFilter.empty() || std::find(typeFilter.begin(), typeFilter.end(), fieldType) != std::end(typeFilter))
{
std::string tmpKey = "feat." + key;
AddChoice(tmpKey, item);
}
}
}
}
void DoExecute() override
......
......@@ -109,8 +109,9 @@ private:
"In overwrite mode, the original features will be lost.");
MandatoryOff("out");
AddParameter(ParameterType_ListView, "feat", "Input features to use for reduction");
AddParameter(ParameterType_Field, "feat", "Input features to use for reduction");
SetParameterDescription("feat", "List of field names in the input vector data used as features for reduction.");
SetVectorData("feat", "in");
AddParameter(ParameterType_Choice, "featout", "Output feature");
SetParameterDescription("featout", "Naming of output features");
......@@ -127,10 +128,11 @@ private:
AddChoice("featout.list", "List");
SetParameterDescription("featout.list", "Use a list with all names");
AddParameter(ParameterType_StringList, "featout.list.names", "Feature name list");
AddParameter(ParameterType_Field, "featout.list.names", "Feature name list");
SetParameterDescription("featout.list.names",
"List of field names for the output "
"features which result from the reduction.");
SetVectorData("featout.list.names", "in");
AddParameter(ParameterType_Int, "pcadim", "Principal component dimension");
SetParameterDescription("pcadim",
......
......@@ -195,8 +195,9 @@ private:
SetParameterDescription("sizey", "size along y in pixels.");
// Channelist Parameters
AddParameter(ParameterType_ListView, "cl", "Output Image channels");
AddParameter(ParameterType_Band, "cl", "Output Image channels");
SetParameterDescription("cl", "Channels to write in the output image.");
SetRasterData("cl", "in");
// Elevation
ElevationParametersHandler::AddElevationParameters(this, "elev");
......
......@@ -97,8 +97,9 @@ private:
"If no system is specified, WGS84 (EPSG: 4326) is used by default.");
MandatoryOff("mode.epsg.code");
AddParameter(ParameterType_ListView, "cl", "Channels");
AddParameter(ParameterType_Band, "cl", "Channels");
SetParameterDescription("cl", "Displayed channels");
SetRasterData("cl", "in");
MandatoryOff("cl");
AddParameter(ParameterType_String, "value", "Pixel Value");
......
......@@ -73,8 +73,9 @@ private:
AddParameter(ParameterType_OutputImage, "out", "Output Image");
SetParameterDescription("out", "The subsampled image");
AddParameter(ParameterType_ListView, "cl", "Channel List");
AddParameter(ParameterType_Band, "cl", "Channel List");
SetParameterDescription("cl", "Selected channels");
SetRasterData("cl", "in");
MandatoryOff("cl");
AddParameter(ParameterType_Int, "rox", "ROI Origin X");
......
......@@ -26,6 +26,7 @@
#include "otbWrapperTypes.h"
#include "otbWrapperTags.h"
#include "otbWrapperParameterGroup.h"
#include "otbWrapperFieldParameter.h"
#include "otbLogger.h"
#include "otbStopwatch.h"
......@@ -249,6 +250,8 @@ public:
* \li ParameterType_InputFilenameListParameter
* \li ParameterType_StringList
* \li ParameterType_ListView
* \li ParameterType_Band
* \li ParameterType_Field
*/
void SetParameterString(std::string const& parameter, std::string value, bool hasUserValueFlag = true);
......@@ -258,6 +261,8 @@ public:
* \li ParameterType_String
* \li ParameterType_StringList
* \li ParameterType_ListView
* \li ParameterType_Band
* \li ParameterType_Field
* \li ParameterType_InputFilename
* \li ParameterType_OutputFilename
* \li ParameterType_Directory
......@@ -426,6 +431,8 @@ public:
*
* Can be called for types:
* \li ParameterType_ListView
* \li ParameterType_Band
* \li ParameterType_Field
*/
void SetListViewSingleSelectionMode(std::string const& parameter, bool status);
......@@ -434,6 +441,8 @@ public:
*
* Can be called for types:
* \li ParameterType_ListView
* \li ParameterType_Band
* \li ParameterType_Field
*/
bool GetListViewSingleSelectionMode(const std::string& parameter);
......@@ -562,6 +571,34 @@ public:
*/
void SetNthParameterInputImageList(std::string const& parameter, const unsigned int& id, ImageBaseType* img);
/**
* Set vector data name from which we choose the fields for a FieldParameter
* \param[in] key The parameter key (must be a FieldParameter)
* \param[in] vectorData vector data name
*/
void SetVectorData(std::string const& key, std::string const& vectorData );
/**
* Set list of allowed field types for a FieldParameter
* \param[in] key The parameter key (must be a FieldParameter)
* \param[in] typeFilter List of allowed types
*/
void SetTypeFilter(std::string const& key, FieldParameter::TypeFilterType const& typeFilter );
/**
* Get list of allowed field types for a FieldParameter
* \param[in] key The parameter key (must be a FieldParameter)
* \return List of allowed types
*/
const FieldParameter::TypeFilterType& GetTypeFilter(std::string const& key ) const;
/**
* Set raster data name from which we choose the bands for a BandParameter
* \param[in] key The parameter key (must be a BandParameter)
* \param[in] rasterData raster data name
*/
void SetRasterData(std::string const& key, std::string const& rasterData );
/**
* Add a value to a parameter list as a string
*
......
/*
* Copyright (C) 2005-2020 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 otbWrapperBandParameter_h
#define otbWrapperBandParameter_h
#include <string>
#include "otbWrapperListViewParameter.h"
namespace otb
{
namespace Wrapper
{
/** \class BandParameter
* \brief This class represents a band parameter selected from a raster file
* for the wrapper framework
*
* \ingroup OTBApplicationEngine
*/
class OTBApplicationEngine_EXPORT BandParameter : public ListViewParameter
{
public:
/** Standard class typedef */
typedef BandParameter Self;
typedef ListViewParameter Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** Defining ::New() static method */
itkNewMacro(Self);
/** RTTI support */
itkTypeMacro(BandParameter, ListViewParameter);
ParameterType GetType() const override
{
return ParameterType_Band;
}
/** Set raster data name from which we choose the fields */
void SetRasterData(std::string rasterData)
{
m_RasterData = std::move(rasterData);
}
/** Get raster data name from which we choose the fields */
const std::string& GetRasterData() const
{
return m_RasterData;
}
protected:
/** Constructor */
BandParameter() = default;
/** Destructor */
~BandParameter() override = default;
std::string m_RasterData;
private:
BandParameter(const BandParameter&) = delete;
void operator=(const BandParameter&) = delete;
}; // End class BandParameter
} // End namespace Wrapper
} // End namespace otb
#endif
/*
* Copyright (C) 2005-2020 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 otbWrapperFieldParameter_h
#define otbWrapperFieldParameter_h
#include <string>
#include "otbWrapperListViewParameter.h"
namespace otb
{
namespace Wrapper
{
/** \class FieldParameter
* \brief This class represents a field parameter selected from a vector file
* for the wrapper framework
*
* \ingroup OTBApplicationEngine
*/
class OTBApplicationEngine_EXPORT FieldParameter : public ListViewParameter
{
public:
/** Standard class typedef */
typedef FieldParameter Self;
typedef ListViewParameter Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** Defining ::New() static method */
itkNewMacro(Self);
/** RTTI support */
itkTypeMacro(FieldParameter, ListViewParameter);
typedef std::vector<OGRFieldType> TypeFilterType;
ParameterType GetType() const override
{
return ParameterType_Field;
}
/** Set vector data name from which we choose the fields */
void SetVectorData(std::string vectorData)
{
m_VectorData = std::move(vectorData);
}
/** Get vector data name from which we choose the fields */
const std::string& GetVectorData() const
{
return m_VectorData;
}
/** Set list of allowed field types */
void SetTypeFilter(TypeFilterType typeFilter)
{
m_TypeFilter = std::move(typeFilter);
}
/** Get list of allowed field types */
const TypeFilterType& GetTypeFilter() const
{
return m_TypeFilter;
}
protected:
/** Constructor */
FieldParameter() = default;
/** Destructor */
~FieldParameter() override = default;
std::string m_VectorData;
TypeFilterType m_TypeFilter;
private:
FieldParameter(const FieldParameter&) = delete;