Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[processing] Only load plotly library on demand (i.e. at time of algo…
…rithm

execution)

Because:
1. It's nicer to show all algorithms on all installs, and give a descriptive
error message to users when they try to run algorithms which depend on Plotly
if the library is missing. Otherwise on some installs these algorithms are
just missing for no apparent reason.

2. The plotly library takes a long time to load on windows (3-4 seconds),
so by moving this load to an on-demand load at time of algorithm execution
we can shave a few seconds off the QGIS startup time for ALL users.
  • Loading branch information
nyalldawson committed Nov 17, 2019
1 parent 8096b0b commit 7c193a3
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 50 deletions.
13 changes: 11 additions & 2 deletions python/plugins/processing/algs/qgis/BarPlot.py
Expand Up @@ -21,9 +21,8 @@
__date__ = 'January 2013'
__copyright__ = '(C) 2013, Victor Olaya'

import plotly as plt
import plotly.graph_objs as go

import warnings

from qgis.core import (QgsFeatureRequest,
QgsProcessingParameterFeatureSource,
Expand Down Expand Up @@ -69,6 +68,16 @@ def displayName(self):
return self.tr('Bar plot')

def processAlgorithm(self, parameters, context, feedback):
try:
# importing plotly throws Python warnings from within the library - filter these out
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=ResourceWarning)
warnings.filterwarnings("ignore", category=ImportWarning)
import plotly as plt
import plotly.graph_objs as go
except ImportError:
raise QgsProcessingException(self.tr('This algorithm requires the Python “plotly” library. Please install this library and try again.'))

source = self.parameterAsSource(parameters, self.INPUT, context)
if source is None:
raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))
Expand Down
13 changes: 11 additions & 2 deletions python/plugins/processing/algs/qgis/BoxPlot.py
Expand Up @@ -21,8 +21,7 @@
__date__ = 'March 2017'
__copyright__ = '(C) 2017, Matteo Ghetta'

import plotly as plt
import plotly.graph_objs as go
import warnings

from qgis.core import (QgsProcessingException,
QgsProcessingParameterFeatureSource,
Expand Down Expand Up @@ -80,6 +79,16 @@ def displayName(self):
return self.tr('Box plot')

def processAlgorithm(self, parameters, context, feedback):
try:
# importing plotly throws Python warnings from within the library - filter these out
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=ResourceWarning)
warnings.filterwarnings("ignore", category=ImportWarning)
import plotly as plt
import plotly.graph_objs as go
except ImportError:
raise QgsProcessingException(self.tr('This algorithm requires the Python “plotly” library. Please install this library and try again.'))

source = self.parameterAsSource(parameters, self.INPUT, context)
if source is None:
raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))
Expand Down
13 changes: 11 additions & 2 deletions python/plugins/processing/algs/qgis/MeanAndStdDevPlot.py
Expand Up @@ -21,8 +21,7 @@
__date__ = 'January 2013'
__copyright__ = '(C) 2013, Victor Olaya'

import plotly as plt
import plotly.graph_objs as go
import warnings

from qgis.core import (QgsProcessingParameterFeatureSource,
QgsProcessingParameterField,
Expand Down Expand Up @@ -68,6 +67,16 @@ def displayName(self):
return self.tr('Mean and standard deviation plot')

def processAlgorithm(self, parameters, context, feedback):
try:
# importing plotly throws Python warnings from within the library - filter these out
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=ResourceWarning)
warnings.filterwarnings("ignore", category=ImportWarning)
import plotly as plt
import plotly.graph_objs as go
except ImportError:
raise QgsProcessingException(self.tr('This algorithm requires the Python “plotly” library. Please install this library and try again.'))

source = self.parameterAsSource(parameters, self.INPUT, context)
if source is None:
raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))
Expand Down
16 changes: 13 additions & 3 deletions python/plugins/processing/algs/qgis/PolarPlot.py
Expand Up @@ -21,9 +21,7 @@
__date__ = 'January 2013'
__copyright__ = '(C) 2013, Victor Olaya'

import plotly as plt
import plotly.graph_objs as go
import numpy as np
import warnings

from qgis.core import (QgsProcessingException,
QgsProcessingParameterFeatureSource,
Expand Down Expand Up @@ -66,6 +64,18 @@ def displayName(self):
return self.tr('Polar plot')

def processAlgorithm(self, parameters, context, feedback):
try:
# importing plotly throws Python warnings from within the library - filter these out
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=ResourceWarning)
warnings.filterwarnings("ignore", category=ImportWarning)
import plotly as plt
import plotly.graph_objs as go
except ImportError:
raise QgsProcessingException(self.tr('This algorithm requires the Python “plotly” library. Please install this library and try again.'))

import numpy as np

source = self.parameterAsSource(parameters, self.INPUT, context)
if source is None:
raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))
Expand Down
46 changes: 16 additions & 30 deletions python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py
Expand Up @@ -22,17 +22,6 @@
__copyright__ = '(C) 2012, Victor Olaya'

import os
import warnings

try:
# importing plotly throws Python warnings from within the library - filter these out
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=ResourceWarning)
warnings.filterwarnings("ignore", category=ImportWarning)
import plotly # NOQA
hasPlotly = True
except:
hasPlotly = False

from qgis.core import (QgsApplication,
QgsProcessingProvider)
Expand All @@ -46,7 +35,9 @@
from .AddTableField import AddTableField
from .Aggregate import Aggregate
from .Aspect import Aspect
from .BarPlot import BarPlot
from .BasicStatistics import BasicStatisticsForField
from .BoxPlot import BoxPlot
from .CheckValidity import CheckValidity
from .Climb import Climb
from .ConcaveHull import ConcaveHull
Expand Down Expand Up @@ -80,6 +71,7 @@
from .KeepNBiggestParts import KeepNBiggestParts
from .KNearestConcaveHull import KNearestConcaveHull
from .LinesToPolygons import LinesToPolygons
from .MeanAndStdDevPlot import MeanAndStdDevPlot
from .MinimumBoundingGeometry import MinimumBoundingGeometry
from .NearestNeighbourAnalysis import NearestNeighbourAnalysis
from .Orthogonalize import Orthogonalize
Expand All @@ -90,6 +82,7 @@
from .PointsInPolygon import PointsInPolygon
from .PointsLayerFromTable import PointsLayerFromTable
from .PointsToPaths import PointsToPaths
from .PolarPlot import PolarPlot
from .PoleOfInaccessibility import PoleOfInaccessibility
from .Polygonize import Polygonize
from .PostGISExecuteSQL import PostGISExecuteSQL
Expand All @@ -104,6 +97,7 @@
from .RandomSelectionWithinSubsets import RandomSelectionWithinSubsets
from .Rasterize import RasterizeAlgorithm
from .RasterCalculator import RasterCalculator
from .RasterLayerHistogram import RasterLayerHistogram
from .RasterLayerStatistics import RasterLayerStatistics
from .RasterSampling import RasterSampling
from .RectanglesOvalsDiamondsFixed import RectanglesOvalsDiamondsFixed
Expand Down Expand Up @@ -135,6 +129,9 @@
from .TruncateTable import TruncateTable
from .UniqueValues import UniqueValues
from .VariableDistanceBuffer import VariableDistanceBuffer
from .VectorLayerHistogram import VectorLayerHistogram
from .VectorLayerScatterplot import VectorLayerScatterplot
from .VectorLayerScatterplot3D import VectorLayerScatterplot3D
from .VectorSplit import VectorSplit
from .VoronoiPolygons import VoronoiPolygons
from .ZonalStatistics import ZonalStatistics
Expand All @@ -156,7 +153,9 @@ def getAlgs(self):
algs = [AddTableField(),
Aggregate(),
Aspect(),
BarPlot(),
BasicStatisticsForField(),
BoxPlot(),
CheckValidity(),
Climb(),
ConcaveHull(),
Expand Down Expand Up @@ -190,6 +189,7 @@ def getAlgs(self):
KeepNBiggestParts(),
KNearestConcaveHull(),
LinesToPolygons(),
MeanAndStdDevPlot(),
MinimumBoundingGeometry(),
NearestNeighbourAnalysis(),
Orthogonalize(),
Expand All @@ -200,6 +200,7 @@ def getAlgs(self):
PointsInPolygon(),
PointsLayerFromTable(),
PointsToPaths(),
PolarPlot(),
PoleOfInaccessibility(),
Polygonize(),
PostGISExecuteSQL(),
Expand All @@ -214,6 +215,7 @@ def getAlgs(self):
RandomSelectionWithinSubsets(),
RasterCalculator(),
RasterizeAlgorithm(),
RasterLayerHistogram(),
RasterLayerStatistics(),
RasterSampling(),
RectanglesOvalsDiamondsFixed(),
Expand Down Expand Up @@ -246,30 +248,14 @@ def getAlgs(self):
TruncateTable(),
UniqueValues(),
VariableDistanceBuffer(),
VectorLayerHistogram(),
VectorLayerScatterplot(),
VectorLayerScatterplot3D(),
VectorSplit(),
VoronoiPolygons(),
ZonalStatistics()
]

if hasPlotly:
from .BarPlot import BarPlot
from .BoxPlot import BoxPlot
from .MeanAndStdDevPlot import MeanAndStdDevPlot
from .PolarPlot import PolarPlot
from .RasterLayerHistogram import RasterLayerHistogram
from .VectorLayerHistogram import VectorLayerHistogram
from .VectorLayerScatterplot import VectorLayerScatterplot
from .VectorLayerScatterplot3D import VectorLayerScatterplot3D

algs.extend([BarPlot(),
BoxPlot(),
MeanAndStdDevPlot(),
PolarPlot(),
RasterLayerHistogram(),
VectorLayerHistogram(),
VectorLayerScatterplot(),
VectorLayerScatterplot3D()])

# to store algs added by 3rd party plugins as scripts
#folder = os.path.join(os.path.dirname(__file__), 'scripts')
#scripts = ScriptUtils.loadFromFolder(folder)
Expand Down
16 changes: 13 additions & 3 deletions python/plugins/processing/algs/qgis/RasterLayerHistogram.py
Expand Up @@ -21,13 +21,13 @@
__date__ = 'January 2013'
__copyright__ = '(C) 2013, Victor Olaya'

import plotly as plt
import plotly.graph_objs as go
import warnings

from qgis.core import (QgsProcessingParameterRasterLayer,
QgsProcessingParameterBand,
QgsProcessingParameterNumber,
QgsProcessingParameterFileDestination)
QgsProcessingParameterFileDestination,
QgsProcessingException)
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
from processing.tools import raster

Expand Down Expand Up @@ -67,6 +67,16 @@ def displayName(self):
return self.tr('Raster layer histogram')

def processAlgorithm(self, parameters, context, feedback):
try:
# importing plotly throws Python warnings from within the library - filter these out
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=ResourceWarning)
warnings.filterwarnings("ignore", category=ImportWarning)
import plotly as plt
import plotly.graph_objs as go
except ImportError:
raise QgsProcessingException(self.tr('This algorithm requires the Python “plotly” library. Please install this library and try again.'))

layer = self.parameterAsRasterLayer(parameters, self.INPUT, context)
band = self.parameterAsInt(parameters, self.BAND, context)
nbins = self.parameterAsInt(parameters, self.BINS, context)
Expand Down
13 changes: 11 additions & 2 deletions python/plugins/processing/algs/qgis/VectorLayerHistogram.py
Expand Up @@ -21,8 +21,7 @@
__date__ = 'January 2013'
__copyright__ = '(C) 2013, Victor Olaya'

import plotly as plt
import plotly.graph_objs as go
import warnings

from qgis.core import (QgsProcessingException,
QgsProcessingParameterFeatureSource,
Expand Down Expand Up @@ -67,6 +66,16 @@ def displayName(self):
return self.tr('Vector layer histogram')

def processAlgorithm(self, parameters, context, feedback):
try:
# importing plotly throws Python warnings from within the library - filter these out
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=ResourceWarning)
warnings.filterwarnings("ignore", category=ImportWarning)
import plotly as plt
import plotly.graph_objs as go
except ImportError:
raise QgsProcessingException(self.tr('This algorithm requires the Python “plotly” library. Please install this library and try again.'))

source = self.parameterAsSource(parameters, self.INPUT, context)
if source is None:
raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))
Expand Down
14 changes: 11 additions & 3 deletions python/plugins/processing/algs/qgis/VectorLayerScatterplot.py
Expand Up @@ -21,9 +21,7 @@
__date__ = 'January 2013'
__copyright__ = '(C) 2013, Victor Olaya'

import plotly as plt
import plotly.graph_objs as go

import warnings
from qgis.core import (QgsProcessingException,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterField,
Expand Down Expand Up @@ -70,6 +68,16 @@ def displayName(self):
return self.tr('Vector layer scatterplot')

def processAlgorithm(self, parameters, context, feedback):
try:
# importing plotly throws Python warnings from within the library - filter these out
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=ResourceWarning)
warnings.filterwarnings("ignore", category=ImportWarning)
import plotly as plt
import plotly.graph_objs as go
except ImportError:
raise QgsProcessingException(self.tr('This algorithm requires the Python “plotly” library. Please install this library and try again.'))

source = self.parameterAsSource(parameters, self.INPUT, context)
if source is None:
raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))
Expand Down
14 changes: 11 additions & 3 deletions python/plugins/processing/algs/qgis/VectorLayerScatterplot3D.py
Expand Up @@ -21,9 +21,7 @@
__date__ = 'January 2013'
__copyright__ = '(C) 2013, Victor Olaya'

import plotly as plt
import plotly.graph_objs as go

import warnings
from qgis.core import (QgsProcessingParameterFeatureSource,
QgsProcessingParameterField,
QgsProcessingParameterFileDestination,
Expand Down Expand Up @@ -76,6 +74,16 @@ def displayName(self):
return self.tr('Vector layer scatterplot 3D')

def processAlgorithm(self, parameters, context, feedback):
try:
# importing plotly throws Python warnings from within the library - filter these out
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=ResourceWarning)
warnings.filterwarnings("ignore", category=ImportWarning)
import plotly as plt
import plotly.graph_objs as go
except ImportError:
raise QgsProcessingException(self.tr('This algorithm requires the Python “plotly” library. Please install this library and try again.'))

source = self.parameterAsSource(parameters, self.INPUT, context)
if source is None:
raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))
Expand Down

0 comments on commit 7c193a3

Please sign in to comment.