Processing.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. """
  2. ***************************************************************************
  3. Processing.py
  4. ---------------------
  5. Date : August 2012
  6. Copyright : (C) 2012 by Victor Olaya
  7. Email : volayaf at gmail dot com
  8. ***************************************************************************
  9. * *
  10. * This program is free software; you can redistribute it and/or modify *
  11. * it under the terms of the GNU General Public License as published by *
  12. * the Free Software Foundation; either version 2 of the License, or *
  13. * (at your option) any later version. *
  14. * *
  15. ***************************************************************************
  16. """
  17. __author__ = 'Victor Olaya'
  18. __date__ = 'August 2012'
  19. __copyright__ = '(C) 2012, Victor Olaya'
  20. import os
  21. import traceback
  22. from qgis.PyQt.QtCore import Qt, QCoreApplication
  23. from qgis.PyQt.QtWidgets import QApplication
  24. from qgis.PyQt.QtGui import QCursor
  25. from qgis.utils import iface
  26. from qgis.core import (QgsMessageLog,
  27. QgsApplication,
  28. QgsMapLayer,
  29. QgsProcessingProvider,
  30. QgsProcessingAlgorithm,
  31. QgsProcessingException,
  32. QgsProcessingParameterDefinition,
  33. QgsProcessingOutputVectorLayer,
  34. QgsProcessingOutputRasterLayer,
  35. QgsProcessingOutputPointCloudLayer,
  36. QgsProcessingOutputMapLayer,
  37. QgsProcessingOutputMultipleLayers,
  38. QgsProcessingFeedback,
  39. QgsRuntimeProfiler)
  40. from qgis.analysis import QgsNativeAlgorithms
  41. import processing
  42. from processing.core.ProcessingConfig import ProcessingConfig
  43. from processing.gui.MessageBarProgress import MessageBarProgress
  44. from processing.gui.RenderingStyles import RenderingStyles
  45. from processing.gui.AlgorithmExecutor import execute
  46. from processing.script import ScriptUtils
  47. from processing.tools import dataobjects
  48. with QgsRuntimeProfiler.profile('Import QGIS Provider'):
  49. from processing.algs.qgis.QgisAlgorithmProvider import QgisAlgorithmProvider # NOQA
  50. with QgsRuntimeProfiler.profile('Import GDAL Provider'):
  51. from processing.algs.gdal.GdalAlgorithmProvider import GdalAlgorithmProvider # NOQA
  52. with QgsRuntimeProfiler.profile('Import Dbms Provider'):
  53. from processing.algs.gdal.DbmsAlgorithmProvider import DbmsAlgorithmProvider # NOQA
  54. with QgsRuntimeProfiler.profile('Import Script Provider'):
  55. from processing.script.ScriptAlgorithmProvider import ScriptAlgorithmProvider # NOQA
  56. # should be loaded last - ensures that all dependent algorithms are available when loading models
  57. from processing.modeler.ModelerAlgorithmProvider import ModelerAlgorithmProvider # NOQA
  58. from processing.modeler.ProjectProvider import ProjectProvider # NOQA
  59. class Processing:
  60. BASIC_PROVIDERS = []
  61. @staticmethod
  62. def activateProvider(providerOrName, activate=True):
  63. provider_id = providerOrName.id() if isinstance(providerOrName, QgsProcessingProvider) else providerOrName
  64. provider = QgsApplication.processingRegistry().providerById(provider_id)
  65. try:
  66. provider.setActive(True)
  67. provider.refreshAlgorithms()
  68. except:
  69. # provider could not be activated
  70. QgsMessageLog.logMessage(Processing.tr('Error: Provider {0} could not be activated\n').format(provider_id),
  71. Processing.tr("Processing"))
  72. @staticmethod
  73. def initialize():
  74. if "model" in [p.id() for p in QgsApplication.processingRegistry().providers()]:
  75. return
  76. with QgsRuntimeProfiler.profile('Initialize'):
  77. # add native provider if not already added
  78. if "native" not in [p.id() for p in QgsApplication.processingRegistry().providers()]:
  79. QgsApplication.processingRegistry().addProvider(
  80. QgsNativeAlgorithms(QgsApplication.processingRegistry()))
  81. # add 3d provider if available and not already added
  82. if "3d" not in [p.id() for p in QgsApplication.processingRegistry().providers()]:
  83. try:
  84. from qgis._3d import Qgs3DAlgorithms
  85. QgsApplication.processingRegistry().addProvider(
  86. Qgs3DAlgorithms(QgsApplication.processingRegistry()))
  87. except ImportError:
  88. # no 3d library available
  89. pass
  90. # Add the basic providers
  91. for c in [
  92. QgisAlgorithmProvider,
  93. # GdalAlgorithmProvider,
  94. ScriptAlgorithmProvider,
  95. ModelerAlgorithmProvider,
  96. ProjectProvider,
  97. # DbmsAlgorithmProvider
  98. ]:
  99. p = c()
  100. if QgsApplication.processingRegistry().addProvider(p):
  101. Processing.BASIC_PROVIDERS.append(p)
  102. if QgsApplication.platform() == 'external':
  103. # for external applications we must also load the builtin providers stored in separate plugins
  104. try:
  105. from grassprovider.Grass7AlgorithmProvider import Grass7AlgorithmProvider
  106. p = Grass7AlgorithmProvider()
  107. if QgsApplication.processingRegistry().addProvider(p):
  108. Processing.BASIC_PROVIDERS.append(p)
  109. except ImportError:
  110. pass
  111. try:
  112. from otbprovider.OtbAlgorithmProvider import OtbAlgorithmProvider
  113. p = OtbAlgorithmProvider()
  114. if QgsApplication.processingRegistry().addProvider(p):
  115. Processing.BASIC_PROVIDERS.append(p)
  116. except ImportError:
  117. pass
  118. for c in [
  119. GdalAlgorithmProvider
  120. ]:
  121. p = c()
  122. if QgsApplication.processingRegistry().addProvider(p):
  123. Processing.BASIC_PROVIDERS.append(p)
  124. # And initialize
  125. ProcessingConfig.initialize()
  126. ProcessingConfig.readSettings()
  127. RenderingStyles.loadStyles()
  128. @staticmethod
  129. def deinitialize():
  130. for p in Processing.BASIC_PROVIDERS:
  131. QgsApplication.processingRegistry().removeProvider(p)
  132. Processing.BASIC_PROVIDERS = []
  133. @staticmethod
  134. def runAlgorithm(algOrName, parameters, onFinish=None, feedback=None, context=None):
  135. if isinstance(algOrName, QgsProcessingAlgorithm):
  136. alg = algOrName
  137. else:
  138. alg = QgsApplication.processingRegistry().createAlgorithmById(algOrName)
  139. if feedback is None:
  140. feedback = QgsProcessingFeedback()
  141. if alg is None:
  142. msg = Processing.tr('Error: Algorithm {0} not found\n').format(algOrName)
  143. feedback.reportError(msg)
  144. raise QgsProcessingException(msg)
  145. if context is None:
  146. context = dataobjects.createContext(feedback)
  147. if context.feedback() is None:
  148. context.setFeedback(feedback)
  149. ok, msg = alg.checkParameterValues(parameters, context)
  150. if not ok:
  151. msg = Processing.tr('Unable to execute algorithm\n{0}').format(msg)
  152. feedback.reportError(msg)
  153. raise QgsProcessingException(msg)
  154. if not alg.validateInputCrs(parameters, context):
  155. feedback.pushInfo(
  156. Processing.tr('Warning: Not all input layers use the same CRS.\nThis can cause unexpected results.'))
  157. ret, results = execute(alg, parameters, context, feedback, catch_exceptions=False)
  158. if ret:
  159. feedback.pushInfo(
  160. Processing.tr('Results: {}').format(results))
  161. if onFinish is not None:
  162. onFinish(alg, context, feedback)
  163. else:
  164. # auto convert layer references in results to map layers
  165. for out in alg.outputDefinitions():
  166. if out.name() not in results:
  167. continue
  168. if isinstance(out, (
  169. QgsProcessingOutputVectorLayer, QgsProcessingOutputRasterLayer, QgsProcessingOutputPointCloudLayer,
  170. QgsProcessingOutputMapLayer)):
  171. result = results[out.name()]
  172. if not isinstance(result, QgsMapLayer):
  173. layer = context.takeResultLayer(result) # transfer layer ownership out of context
  174. if layer:
  175. results[out.name()] = layer # replace layer string ref with actual layer (+ownership)
  176. elif isinstance(out, QgsProcessingOutputMultipleLayers):
  177. result = results[out.name()]
  178. if result:
  179. layers_result = []
  180. for l in result:
  181. if not isinstance(l, QgsMapLayer):
  182. layer = context.takeResultLayer(l) # transfer layer ownership out of context
  183. if layer:
  184. layers_result.append(layer)
  185. else:
  186. layers_result.append(l)
  187. else:
  188. layers_result.append(l)
  189. results[
  190. out.name()] = layers_result # replace layers strings ref with actual layers (+ownership)
  191. else:
  192. msg = Processing.tr("There were errors executing the algorithm.")
  193. feedback.reportError(msg)
  194. raise QgsProcessingException(msg)
  195. if isinstance(feedback, MessageBarProgress):
  196. feedback.close()
  197. return results
  198. @staticmethod
  199. def tr(string, context=''):
  200. if context == '':
  201. context = 'Processing'
  202. return QCoreApplication.translate(context, string)