diff --git a/Modules/Core/Common/include/otbLogger.h b/Modules/Core/Common/include/otbLogger.h index 4dd6825bd146d10a2fc6a37464db8d3e290e2fe2..6ae206fe2611038834f5721c01c67126420afdc2 100644 --- a/Modules/Core/Common/include/otbLogger.h +++ b/Modules/Core/Common/include/otbLogger.h @@ -56,6 +56,8 @@ public: */ static Logger * Instance(); + void ResetOutputs(); + static Pointer New(); itkCreateAnotherMacro( Logger ) itkCloneMacro( Logger ) diff --git a/Modules/Core/Common/include/otbStandardOneLineFilterWatcher.h b/Modules/Core/Common/include/otbStandardOneLineFilterWatcher.h index 9cbf761b4c12b5fec6f9309ee6ab38ddfe5cf0f8..7abc307908b0ea856f380208666e61c38402135e 100644 --- a/Modules/Core/Common/include/otbStandardOneLineFilterWatcher.h +++ b/Modules/Core/Common/include/otbStandardOneLineFilterWatcher.h @@ -25,6 +25,7 @@ #include <iosfwd> #include "otbFilterWatcherBase.h" +#include "otbStandardOutputPrintCallback.h" namespace otb { @@ -46,15 +47,16 @@ namespace otb * StandardOneLineFilterWatcher watcher(thresholdFilter, "Threshold"); * \endcode * + * \see otb::StandardOutputPrintCallback * \see itk::SimpleFilterWatcher * \see otb::fltkFilterWatcher * * \ingroup OTBCommon */ -class OTBCommon_EXPORT StandardOneLineFilterWatcher : public FilterWatcherBase +template <class PrintCallbackType = StandardOutputPrintCallback> +class OTBCommon_EXPORT_TEMPLATE StandardOneLineFilterWatcher : public FilterWatcherBase { public: - /** Constructor. Takes a ProcessObject to monitor and an optional * comment string that is prepended to each event message. */ StandardOneLineFilterWatcher(itk::ProcessObject* process, @@ -66,6 +68,9 @@ public: /** Default constructor */ StandardOneLineFilterWatcher(); + /** Destrucotr */ + ~StandardOneLineFilterWatcher() override = default; + /** Get/Set number of stars */ void SetStars(int count) { @@ -76,6 +81,12 @@ public: return m_StarsCount; } + /** Set the callback class */ + void SetCallback(PrintCallbackType * callback) + { + m_Callback = callback; + } + protected: /** Callback method to show the ProgressEvent */ @@ -89,16 +100,31 @@ protected: private: - /** Stars coutning */ + /** Stars counting */ int m_StarsCount; + /** Current number of stars, we keep track of this to avoid reprinting the + * progress if it hasn't changed */ int m_CurrentNbStars; - bool m_CoutIsConsole; - + /** If the output is not interactive (e.g. it is redirected to a file), it + * is buffered and only written at the end of the processing */ std::string m_Buffer; + + /** The point to the callback used for printing. It is set to the default + * callback on construction and can be changed later using the setter. + * Delete will not be called on this pointer. */ + PrintCallbackType * m_Callback; + + /** A default callback created in the constructor and deleted in the + * destructor. */ + std::shared_ptr<PrintCallbackType> m_DefaultCallback; }; } // end namespace otb +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbStandardOneLineFilterWatcher.hxx" +#endif + #endif diff --git a/Modules/Core/Common/src/otbStandardOneLineFilterWatcher.cxx b/Modules/Core/Common/include/otbStandardOneLineFilterWatcher.hxx similarity index 65% rename from Modules/Core/Common/src/otbStandardOneLineFilterWatcher.cxx rename to Modules/Core/Common/include/otbStandardOneLineFilterWatcher.hxx index f247061da6b4dca59baa48d8b4cf5bb9d7ac3ce8..56489471fc73fa0c5f7246909051c9d04cede370 100644 --- a/Modules/Core/Common/src/otbStandardOneLineFilterWatcher.cxx +++ b/Modules/Core/Common/include/otbStandardOneLineFilterWatcher.hxx @@ -19,6 +19,9 @@ * limitations under the License. */ +#ifndef otbStandardOneLineFilterWatcher_hxx +#define otbStandardOneLineFilterWatcher_hxx + #include <iostream> #include <sstream> @@ -28,37 +31,43 @@ namespace otb { - -StandardOneLineFilterWatcher +template<class PrintCallbackType> +StandardOneLineFilterWatcher<PrintCallbackType> ::StandardOneLineFilterWatcher() : m_StarsCount(50), - m_CurrentNbStars(-1), - m_CoutIsConsole( System::IsInteractive(1) ) + m_CurrentNbStars(-1) { + m_DefaultCallback = std::make_shared<PrintCallbackType>() ; + m_Callback = m_DefaultCallback.get(); } -StandardOneLineFilterWatcher +template<class PrintCallbackType> +StandardOneLineFilterWatcher<PrintCallbackType> ::StandardOneLineFilterWatcher(itk::ProcessObject* process, const char *comment) : FilterWatcherBase(process, comment), m_StarsCount(50), - m_CurrentNbStars(-1), - m_CoutIsConsole( System::IsInteractive(1) ) + m_CurrentNbStars(-1) { + m_DefaultCallback = std::make_shared<PrintCallbackType>() ; + m_Callback = m_DefaultCallback.get(); } -StandardOneLineFilterWatcher +template<class PrintCallbackType> +StandardOneLineFilterWatcher<PrintCallbackType> ::StandardOneLineFilterWatcher(itk::ProcessObject* process, const std::string& comment) : FilterWatcherBase(process, comment.c_str()), m_StarsCount(50), - m_CurrentNbStars(-1), - m_CoutIsConsole( System::IsInteractive(1) ) + m_CurrentNbStars(-1) { + m_DefaultCallback = std::make_shared<PrintCallbackType>() ; + m_Callback = m_DefaultCallback.get(); } +template<class PrintCallbackType> void -StandardOneLineFilterWatcher +StandardOneLineFilterWatcher<PrintCallbackType> ::ShowProgress() { if (m_Process) @@ -90,9 +99,10 @@ StandardOneLineFilterWatcher oss << m_Comment << ": " << progressPercent << "% [" << stars << blanks << "]"; - if (m_CoutIsConsole) + if (m_Callback->IsInteractive()) { - std::cout << "\r" << oss.str() << std::flush; + m_Callback->Call("\r" + oss.str()); + m_Callback->Flush(); } else { @@ -104,29 +114,31 @@ StandardOneLineFilterWatcher } } +template<class PrintCallbackType> void -StandardOneLineFilterWatcher +StandardOneLineFilterWatcher<PrintCallbackType> ::StartFilter() { m_Stopwatch.Start(); } +template<class PrintCallbackType> void -StandardOneLineFilterWatcher +StandardOneLineFilterWatcher<PrintCallbackType> ::EndFilter() { m_Stopwatch.Stop(); - if (m_Process && !m_CoutIsConsole) + if (m_Process && !m_Callback->IsInteractive()) { - std::cout << m_Buffer; + m_Callback->Call(m_Buffer); m_Buffer = std::string(""); } - std::cout << " ("; - m_Stopwatch.GetElapsedHumanReadableTime(std::cout); - std::cout << ")" - << std::endl; + m_Callback->Call(" (" + m_Stopwatch.GetElapsedHumanReadableTime() + ")\n"); + } } // end namespace otb + +#endif diff --git a/Modules/Core/Common/include/otbStandardOutputPrintCallback.h b/Modules/Core/Common/include/otbStandardOutputPrintCallback.h new file mode 100644 index 0000000000000000000000000000000000000000..2804a98cfc365dc6b1d8b362cebd7d483d73c761 --- /dev/null +++ b/Modules/Core/Common/include/otbStandardOutputPrintCallback.h @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#ifndef otbStandardOutputPrintCallback_h +#define otbStandardOutputPrintCallback_h + +#include "otbSystem.h" + +namespace otb +{ + +/** \class StandardOutputPrintCallback + * \brief Class with printing callback methods using the standard output + * + * This class defines the Call method, used to write a string the standard + * output, the Flush method, used to flush it, and the IsInteractive + * method used to determine if the output is the console. + * + * \see otb::StandardOneLineFilterWatcher + * + * \ingroup OTBCommon + */ + +class OTBCommon_EXPORT StandardOutputPrintCallback +{ +public: + /** Constructor */ + StandardOutputPrintCallback() :m_IsInteractive( System::IsInteractive(1)) {}; + + /** Destructor */ + virtual ~StandardOutputPrintCallback() = default; + + /** Write a string to a buffer */ + void Call(std::string const& content); + + /** Flush the buffer */ + void Flush(); + + /** Determine if the output is interactive */ + bool IsInteractive(); + +private: + /** flag determining if the output is interactive */ + bool m_IsInteractive; +}; + +} // namespace otb + +#endif // otbStandardOutputPrintCallback_h diff --git a/Modules/Core/Common/src/CMakeLists.txt b/Modules/Core/Common/src/CMakeLists.txt index 91abc0b63f601f34421480cc33e3c12d6320f719..cfbef0afd4cc2b77b1e28995fb414d092ea4c68c 100644 --- a/Modules/Core/Common/src/CMakeLists.txt +++ b/Modules/Core/Common/src/CMakeLists.txt @@ -25,12 +25,12 @@ set(OTBCommon_SRC otbStandardWriterWatcher.cxx otbUtils.cxx otbConfigurationManager.cxx - otbStandardOneLineFilterWatcher.cxx otbWriterWatcherBase.cxx otbStopwatch.cxx otbStringToHTML.cxx otbExtendedFilenameHelper.cxx otbLogger.cxx + otbStandardOutputPrintCallback.cxx ) add_library(OTBCommon ${OTBCommon_SRC}) diff --git a/Modules/Core/Common/src/otbLogger.cxx b/Modules/Core/Common/src/otbLogger.cxx index e6ba5c2b260eec3bb6ed968d3487ead81718a21d..20685d1651d1bc4d249ab6d862acdc518fcde3e9 100644 --- a/Modules/Core/Common/src/otbLogger.cxx +++ b/Modules/Core/Common/src/otbLogger.cxx @@ -49,16 +49,14 @@ Logger * Logger::CreateInstance() { Logger * logger = new Logger; - // By default, redirect logs to std::cout - itk::StdStreamLogOutput::Pointer defaultOutput = - itk::StdStreamLogOutput::New(); + // By default redirect logs to std::cout + itk::StdStreamLogOutput::Pointer defaultOutput = itk::StdStreamLogOutput::New(); defaultOutput->SetStream(std::cout); - logger->AddLogOutput(defaultOutput); + return logger; } - Logger * Logger::Instance() { static Logger * logger_singleton = CreateInstance(); @@ -110,6 +108,11 @@ void Logger::LogSetupInformation() } } +void Logger::ResetOutputs() +{ + m_Output = itk::MultipleLogOutput::New(); +} + bool Logger::IsLogSetupInformationDone() { return m_LogSetupInfoDone; diff --git a/Modules/Core/Common/src/otbStandardOutputPrintCallback.cxx b/Modules/Core/Common/src/otbStandardOutputPrintCallback.cxx new file mode 100644 index 0000000000000000000000000000000000000000..2f41413405d42afcb0d4e372fcfb6f02698148ed --- /dev/null +++ b/Modules/Core/Common/src/otbStandardOutputPrintCallback.cxx @@ -0,0 +1,47 @@ +/* + * 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 "otbStandardOutputPrintCallback.h" + +namespace otb +{ + +void +StandardOutputPrintCallback +::Call(std::string const& content) +{ + std::cout << content; +} + +void +StandardOutputPrintCallback +::Flush() +{ + std::cout << std::flush; +} + +bool +StandardOutputPrintCallback +::IsInteractive() +{ + return m_IsInteractive; +} + +} // namespace otb diff --git a/Modules/Core/Common/test/otbStandardOneLineFilterWatcherTest.cxx b/Modules/Core/Common/test/otbStandardOneLineFilterWatcherTest.cxx index 5ef1f5eac1bde05480692300f210578910667dcc..dfd9bfcdac45585536754210927515941d98db77 100644 --- a/Modules/Core/Common/test/otbStandardOneLineFilterWatcherTest.cxx +++ b/Modules/Core/Common/test/otbStandardOneLineFilterWatcherTest.cxx @@ -38,7 +38,7 @@ int otbStandardOneLineFilterWatcherTest(int itkNotUsed(argc), char * argv[]) typedef itk::GradientMagnitudeImageFilter<ImageType, ImageType> FilterType; FilterType::Pointer gradient = FilterType::New(); - typedef otb::StandardOneLineFilterWatcher WatcherType; + typedef otb::StandardOneLineFilterWatcher<> WatcherType; WatcherType watcher1(gradient, "Gradient"); gradient->SetInput(reader->GetOutput()); diff --git a/Modules/IO/IOGDAL/test/otbGDALOverviewsBuilder.cxx b/Modules/IO/IOGDAL/test/otbGDALOverviewsBuilder.cxx index 4452cb65fc3c74273d773f5930c9ba1e5987a3e4..f250c83b96e0b9c32e1dec450357bd58d2369bda 100644 --- a/Modules/IO/IOGDAL/test/otbGDALOverviewsBuilder.cxx +++ b/Modules/IO/IOGDAL/test/otbGDALOverviewsBuilder.cxx @@ -42,7 +42,7 @@ int otbGDALOverviewsBuilder(int itkNotUsed(argc), char* argv[]) filter->SetResamplingMethod(resamp); { - StandardOneLineFilterWatcher watcher(filter,"Overviews creation"); + StandardOneLineFilterWatcher<> watcher(filter,"Overviews creation"); filter->Update(); } diff --git a/Modules/Visualization/MonteverdiCore/src/mvdVectorImageModel.cxx b/Modules/Visualization/MonteverdiCore/src/mvdVectorImageModel.cxx index 6470adfd61825a585696cb142d3a7c3252073d0c..24772864ba47f864dd127540874094d7b2f45435 100644 --- a/Modules/Visualization/MonteverdiCore/src/mvdVectorImageModel.cxx +++ b/Modules/Visualization/MonteverdiCore/src/mvdVectorImageModel.cxx @@ -260,7 +260,7 @@ VectorImageModel try { - otb::StandardOneLineFilterWatcher watcher( + otb::StandardOneLineFilterWatcher<> watcher( filter, ToStdString( tr( "Overviews creation: " ) ) ); diff --git a/Modules/Wrappers/CommandLine/include/otbWrapperCommandLineLauncher.h b/Modules/Wrappers/CommandLine/include/otbWrapperCommandLineLauncher.h index cc28ee8e9cd3b549e15f8a36005e67a06f644538..9e097a67cfafd11f96efc38867ea37e4b643d62b 100644 --- a/Modules/Wrappers/CommandLine/include/otbWrapperCommandLineLauncher.h +++ b/Modules/Wrappers/CommandLine/include/otbWrapperCommandLineLauncher.h @@ -76,7 +76,7 @@ public: INVALIDNUMBEROFVALUE, DEFAULT} ParamResultType; /** Filter watcher list type */ - typedef std::vector<StandardOneLineFilterWatcher *> WatcherListType; + typedef std::vector<StandardOneLineFilterWatcher<> *> WatcherListType; /** Command Member */ typedef itk::MemberCommand< Self > AddProcessCommandType; diff --git a/Modules/Wrappers/CommandLine/src/otbWrapperCommandLineLauncher.cxx b/Modules/Wrappers/CommandLine/src/otbWrapperCommandLineLauncher.cxx index bed8cd21dcbbfd8af0cf2cd0491151a2d7aa5a0e..a68201fa8f497ffdd086e9945cc6d010cb7be03a 100644 --- a/Modules/Wrappers/CommandLine/src/otbWrapperCommandLineLauncher.cxx +++ b/Modules/Wrappers/CommandLine/src/otbWrapperCommandLineLauncher.cxx @@ -596,7 +596,7 @@ void CommandLineLauncher::LinkWatchers(itk::Object * itkNotUsed(caller), const i { const AddProcessToWatchEvent* eventToWatch = dynamic_cast<const AddProcessToWatchEvent*> (&event); - StandardOneLineFilterWatcher * watch = new StandardOneLineFilterWatcher(eventToWatch->GetProcess(), + auto watch = new StandardOneLineFilterWatcher<>(eventToWatch->GetProcess(), eventToWatch->GetProcessDescription()); m_WatcherList.push_back(watch); } diff --git a/Modules/Wrappers/SWIG/src/itkBase.includes b/Modules/Wrappers/SWIG/src/itkBase.includes index d9f1d3573371324b5fd4b8532d1a049059be70f6..673a86cfee49a6d705834bddb542b8e8eb79d1da 100644 --- a/Modules/Wrappers/SWIG/src/itkBase.includes +++ b/Modules/Wrappers/SWIG/src/itkBase.includes @@ -29,6 +29,8 @@ #include "itkCommand.h" +#include "itkLogOutput.h" + typedef itk::LightObject itkLightObject; typedef itk::LightObject::Pointer itkLightObject_Pointer; typedef itk::Object itkObject; @@ -60,4 +62,6 @@ typedef itk::EndPickEvent itkEndPickEvent; typedef itk::AbortCheckEvent itkAbortCheckEvent; typedef itk::UserEvent itkUserEvent; +typedef itk::LogOutput itkLogOutput; + #endif diff --git a/Modules/Wrappers/SWIG/src/otbApplication.i b/Modules/Wrappers/SWIG/src/otbApplication.i index 63c629d99e3e7a88158958061b30e2b1d03bbb44..6f84595c2462083646ae6a559896e058831c0e66 100644 --- a/Modules/Wrappers/SWIG/src/otbApplication.i +++ b/Modules/Wrappers/SWIG/src/otbApplication.i @@ -203,6 +203,13 @@ public: } // end of namespace otb +#if SWIGPYTHON + + +%include "otbPythonLogOutput.i" +#endif + + class Application: public itkObject { public: @@ -217,6 +224,31 @@ public: int Execute(); int ExecuteAndWriteOutput(); +#if SWIGPYTHON + Logger* GetLogger(); +#endif + unsigned long itk::Object::AddObserver(const EventObject & event, + Command * command); + + +#if SWIGPYTHON + %extend + { + /** SetupLogger : Add the PythonLogOutput and setup the progress + * reporting for the application */ + %pythoncode + { + def SetupLogger(self): + logger = self.GetLogger() + logger.AddLogOutput(_libraryLogOutput.GetPointer()) + + self.AddObserver(AddProcessToWatchEvent(), + _libraryProgressReportManager.GetAddProcessCommand() + ) + } + } +#endif // SWIGPYTHON + std::vector<std::string> GetParametersKeys(bool recursive = true); Parameter* Application::GetParameterByKey(std::string name); std::string GetParameterName(std::string); @@ -877,7 +909,21 @@ class Registry : public itkObject public: static std::vector<std::string> GetAvailableApplications(); + #if SWIGPYTHON + %rename("CreateApplicationWithoutLogger") CreateApplication; + static Application_Pointer CreateApplication(const std::string& name); + %pythoncode + { + @staticmethod + def CreateApplication(name): + application = _otbApplication.Registry_CreateApplicationWithoutLogger(name) + if application is not None: + application.SetupLogger() + return application + } + #else static Application_Pointer CreateApplication(const std::string& name); + #endif static void AddApplicationPath(std::string newpath); static void SetApplicationPath(std::string newpath); static void CleanRegistry(); diff --git a/Modules/Wrappers/SWIG/src/otbPythonLogOutput.i b/Modules/Wrappers/SWIG/src/otbPythonLogOutput.i new file mode 100644 index 0000000000000000000000000000000000000000..4bd7852b2ee7540e8cacb172ecbca7ba2d376ffa --- /dev/null +++ b/Modules/Wrappers/SWIG/src/otbPythonLogOutput.i @@ -0,0 +1,113 @@ +/* + * 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. + */ + +#if SWIGPYTHON + +%module(directors="1") cb +%{ + #include "otbPythonLogOutput.h" + #include "otbSwigPrintCallback.h" +%} + +%feature("director") SwigPrintCallback; + +%include "otbSwigPrintCallback.h" + +class itkLogOutput : public itkObject +{ +protected: + itkLogOutput(); + ~itkLogOutput(); +}; + +/** This Callback class can be called from C++ to print, flush and to determine + * if stdout is redirected */ +%pythoncode + { + class PythonPrintCallback(SwigPrintCallback): + def __init__(self): + super(PythonPrintCallback, self).__init__() + def Call(self, content): + sys.stdout.write(content) + def Flush(self): + sys.stdout.flush() + def IsInteractive(self): + return sys.stdout.isatty() + } + +class PythonLogOutput : public itkLogOutput +{ +public: + static PythonLogOutput_Pointer New(); + virtual void Delete(); + void SetCallback(otb::SwigPrintCallback* callback); + virtual void Write(std::string const & content); + +protected: + PythonLogOutput(); +}; + +DECLARE_REF_COUNT_CLASS( PythonLogOutput ) + +class Logger +{ +public: + virtual void AddLogOutput(itkLogOutput *output); + static Logger * Instance(); + void ResetOutputs(); +protected: + Logger(); + virtual ~Logger(); + +}; + +class ProgressReporterManager: public itkObject +{ +public: + /** Default constructor */ + + static ProgressReporterManager_Pointer New(); + virtual void Delete(); + void DeleteWatcherList(); + void SetLogOutputCallback(otb::SwigPrintCallback* callback); + itkCommand* GetAddProcessCommand(); + +protected: + ProgressReporterManager(); +}; + +DECLARE_REF_COUNT_CLASS( ProgressReporterManager ) + +/** Create the required objects for logging. Logger.Instance() is reset in + * order to replace the itkStdStreamLogOutput by a PythonLogOutput */ +%pythoncode { + _libraryLogOutput = PythonLogOutput_New() + _libraryLogCallback = PythonPrintCallback() + _libraryProgressReportManager = ProgressReporterManager_New() + + Logger.Instance().ResetOutputs() + _libraryLogOutput.SetCallback(_libraryLogCallback) + Logger.Instance().AddLogOutput(_libraryLogOutput.GetPointer()) + + _libraryProgressReportManager.SetLogOutputCallback(_libraryLogCallback) + +} + +#endif diff --git a/Modules/Wrappers/SWIG/src/otbWrapperSWIGIncludes.h b/Modules/Wrappers/SWIG/src/otbWrapperSWIGIncludes.h index 3e1bbf56d7e7ac7f58089754e7464bf56bdbe37a..603910cc06fbbbcd359580d744d7de7618ca2ce5 100644 --- a/Modules/Wrappers/SWIG/src/otbWrapperSWIGIncludes.h +++ b/Modules/Wrappers/SWIG/src/otbWrapperSWIGIncludes.h @@ -39,4 +39,18 @@ typedef otb::Wrapper::ComplexInputImageParameter ComplexInputImageParame typedef otb::Wrapper::ImageBaseType ImageBaseType; +#if defined(SWIGPYTHON) +#include "otbPythonLogOutput.h" +#include "otbLogger.h" +#include "otbProgressReporterManager.h" + +typedef otb::Logger Logger; +typedef otb::Logger::Pointer Logger_Pointer; +typedef otb::SwigPrintCallback SwigPrintCallback; +typedef otb::PythonLogOutput PythonLogOutput; +typedef otb::PythonLogOutput::Pointer PythonLogOutput_Pointer; +typedef otb::ProgressReporterManager ProgressReporterManager; +typedef otb::ProgressReporterManager::Pointer ProgressReporterManager_Pointer; +#endif + #endif diff --git a/Modules/Wrappers/SWIG/src/python/CMakeLists.txt b/Modules/Wrappers/SWIG/src/python/CMakeLists.txt index 01d94c050f07eb3e9f592155824d0a117a9497f7..6a7b288b5cb9ea944662a3fccaf88c4b1181be0c 100644 --- a/Modules/Wrappers/SWIG/src/python/CMakeLists.txt +++ b/Modules/Wrappers/SWIG/src/python/CMakeLists.txt @@ -32,8 +32,15 @@ set(SWIG_MODULE_otbApplication_EXTRA_DEPS ${CMAKE_CURRENT_SOURCE_DIR}/../Python.i ${CMAKE_CURRENT_SOURCE_DIR}/../PyCommand.i itkPyCommand.h + otbSwigPrintCallback.h + otbPythonLogOutput.h + otbProgressReporterManager.h OTBApplicationEngine) -SWIG_add_module( otbApplication python ../otbApplication.i otbApplicationPYTHON_wrap.cxx itkPyCommand.cxx ) +SWIG_add_module( otbApplication python ../otbApplication.i + otbApplicationPYTHON_wrap.cxx + itkPyCommand.cxx + ../python/otbPythonLogOutput.cxx + ../python/otbProgressReporterManager.cxx) SWIG_link_libraries( otbApplication ${PYTHON_LIBRARIES} OTBApplicationEngine ) set_target_properties(_otbApplication PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SWIG_OUTDIR}) diff --git a/Modules/Wrappers/SWIG/src/python/otbProgressReporterManager.cxx b/Modules/Wrappers/SWIG/src/python/otbProgressReporterManager.cxx new file mode 100644 index 0000000000000000000000000000000000000000..e3a6ac541739b337fea15b1597a186b559031042 --- /dev/null +++ b/Modules/Wrappers/SWIG/src/python/otbProgressReporterManager.cxx @@ -0,0 +1,60 @@ +/* + * 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 "otbProgressReporterManager.h" +#include "otbWrapperAddProcessToWatchEvent.h" + +namespace otb +{ + +ProgressReporterManager::ProgressReporterManager() +{ + // Add the callback to be added when a AddProcessToWatch event is invoked + m_AddProcessCommand = AddProcessCommandType::New(); + m_AddProcessCommand->SetCallbackFunction(this, &ProgressReporterManager::LinkWatchers); +} + +ProgressReporterManager::~ProgressReporterManager() +{ + this->DeleteWatcherList(); +} + +void ProgressReporterManager::DeleteWatcherList() +{ + //Delete all stored progress reporter + for (auto watcher: m_WatcherList) + { + delete watcher; + } + m_WatcherList.clear(); +} + +void ProgressReporterManager::LinkWatchers(itk::Object* itkNotUsed(caller), const itk::EventObject& event) +{ + if (typeid(otb::Wrapper::AddProcessToWatchEvent) == typeid(event)) + { + const Wrapper::AddProcessToWatchEvent* eventToWatch = dynamic_cast<const Wrapper::AddProcessToWatchEvent*>(&event); + + auto watch = new WatcherType(eventToWatch->GetProcess(), eventToWatch->GetProcessDescription()); + watch->SetCallback(m_Callback); + m_WatcherList.push_back(watch); + } +} +} diff --git a/Modules/Wrappers/SWIG/src/python/otbProgressReporterManager.h b/Modules/Wrappers/SWIG/src/python/otbProgressReporterManager.h new file mode 100644 index 0000000000000000000000000000000000000000..ec15926fd20ad0b91ac238f0fbc1b7e61b0e4c1b --- /dev/null +++ b/Modules/Wrappers/SWIG/src/python/otbProgressReporterManager.h @@ -0,0 +1,100 @@ +/* + * 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. + */ + +#ifndef otbProgressReporterManager_h +#define otbProgressReporterManager_h + +#include "itkCommand.h" +#include "otbWrapperApplication.h" + +#include "otbSwigPrintCallback.h" +#include "otbStandardOneLineFilterWatcher.h" + +namespace otb +{ + +/** \class ProgressReporterManager + * \brief Class to manage progress reporting with callback printing. + * + * This class stores the command used to create CallbackProgressReporter + * using an Observer. The created CallbackProgressReporter are also stored + * in this class. + */ +class ProgressReporterManager : public itk::Object +{ +public: + /** Standard class typedefs. */ + typedef ProgressReporterManager Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + itkTypeMacro(ProgressReporterManager, itk::Object); + + itkNewMacro(ProgressReporterManager); + + typedef SwigPrintCallback CallbackType; + typedef StandardOneLineFilterWatcher<CallbackType> WatcherType; + + /** Filter watcher list type */ + typedef std::vector<WatcherType *> WatcherListType; + + /** Command Member */ + typedef itk::MemberCommand<Self> AddProcessCommandType; + + /** Set the logger callback function */ + void SetLogOutputCallback(CallbackType* callback) + { + m_Callback = callback; + this->Modified(); + } + + /** Getter to AddProcessCommand */ + AddProcessCommandType* GetAddProcessCommand() + { + return m_AddProcessCommand.GetPointer(); + } + + /** Delete all watchers */ + void DeleteWatcherList(); + +protected: + /** Default constructor */ + ProgressReporterManager(); + + /** Destructor. */ + ~ProgressReporterManager() override; + + /** Load the watchers for internal progress and writing progress report. */ + void LinkWatchers(itk::Object* caller, const itk::EventObject& event); + +private: + /** The LogOutputCallback used for printing */ + CallbackType* m_Callback; + + /** Command associated to the LinkWatchers command */ + AddProcessCommandType::Pointer m_AddProcessCommand; + + /** container storing all the watchers (CallbackProgressReporter) */ + WatcherListType m_WatcherList; +}; +} + +#endif // otbProgressReporterManager_h diff --git a/Modules/Wrappers/SWIG/src/python/otbPythonLogOutput.cxx b/Modules/Wrappers/SWIG/src/python/otbPythonLogOutput.cxx new file mode 100644 index 0000000000000000000000000000000000000000..d8f703c4b8d1eb4b2f6a932d7e02c0a648b6fc15 --- /dev/null +++ b/Modules/Wrappers/SWIG/src/python/otbPythonLogOutput.cxx @@ -0,0 +1,50 @@ +/* + * 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 "otbPythonLogOutput.h" + +namespace otb +{ +void PythonLogOutput::Flush() +{ + m_Callback->Flush(); +} + +void PythonLogOutput::Write(double timestamp) +{ + m_Callback->Call(std::to_string(timestamp)); +} + +void PythonLogOutput::Write(std::string const& content) +{ + m_Callback->Call(content); +} + +void PythonLogOutput::Write(std::string const& content, double timestamp) +{ + m_Callback->Call(std::to_string(timestamp) + " : " + content); +} + +void PythonLogOutput::PrintSelf(std::ostream& os, itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); +} + +} // namespace otb diff --git a/Modules/Wrappers/SWIG/src/python/otbPythonLogOutput.h b/Modules/Wrappers/SWIG/src/python/otbPythonLogOutput.h new file mode 100644 index 0000000000000000000000000000000000000000..d8e8cfeed22a8f9a04dba0612bda6e4d3259eaf2 --- /dev/null +++ b/Modules/Wrappers/SWIG/src/python/otbPythonLogOutput.h @@ -0,0 +1,82 @@ +/* + * 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. + */ + +#ifndef otbPythonLogOutput_h +#define otbPythonLogOutput_h + +#include "itkLogOutput.h" +#include "otbSwigPrintCallback.h" + +namespace otb +{ + +/** \class LogOutputCallback + * \brief A itk::LogOutput using a LogOutputCallback + * + * This class delegates the Write and Flush methods to a LogOutputCallback + */ +class PythonLogOutput : public itk::LogOutput +{ +public: + typedef PythonLogOutput Self; + typedef itk::LogOutput Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + typedef SwigPrintCallback CallbackType; + itkTypeMacro(PythonLogOutput, itk::LogOutput); + + itkNewMacro(PythonLogOutput); + + /** Set the callback method */ + void SetCallback(CallbackType* callback) + { + m_Callback = callback; + this->Modified(); + } + + /** flush a buffer */ + virtual void Flush() override; + + /** Write to a buffer */ + virtual void Write(double timestamp) override; + + /** Write to a buffer */ + virtual void Write(std::string const& content) override; + + /** Write to a buffer */ + virtual void Write(std::string const& content, double timestamp) override; + +protected: + /** Constructor */ + PythonLogOutput() = default; + + /** Destructor */ + ~PythonLogOutput() override = default; + + virtual void PrintSelf(std::ostream& os, itk::Indent indent) const override; + +private: + CallbackType* m_Callback; +}; + +} // namespace otb + +#endif // otbPythonLogOutput_h diff --git a/Modules/Wrappers/SWIG/src/python/otbSwigPrintCallback.h b/Modules/Wrappers/SWIG/src/python/otbSwigPrintCallback.h new file mode 100644 index 0000000000000000000000000000000000000000..e17a0087304b94a4cb9947b5bc1d021711dc80e8 --- /dev/null +++ b/Modules/Wrappers/SWIG/src/python/otbSwigPrintCallback.h @@ -0,0 +1,58 @@ +/* + * 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. + */ + +#ifndef otbSwigPrintCallbackCallback_h +#define otbSwigPrintCallbackCallback_h + +namespace otb +{ + +/** \class SwigPrintCallback + * \brief Interface for a printing callback method + * + * This class defines the Call method, used to write a string, the Flush + * method, used to flush a bugger, and the Isatty method used to determine + * if the output is interactive. This class is the base class of the Python + * class PythonLogOutputCallback, that uses Swig directors to override these + * methods. + */ + +class SwigPrintCallback +{ +public: + /** Constructor */ + SwigPrintCallback() = default; + + /** Destructor */ + virtual ~SwigPrintCallback() = default; + + /** Write a string to a buffer */ + virtual void Call(std::string const&) {}; + + /** Flush the buffer */ + virtual void Flush() {}; + + /** Determine if the bufer is interactive */ + virtual bool IsInteractive() {return false;}; +}; + +} // namespace otb + +#endif // otbPythonLogOutputCallback_h