BoxPlot.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. """
  2. ***************************************************************************
  3. BarPlot.py
  4. ---------------------
  5. Date : March 2015
  6. Copyright : (C) 2017 by Matteo Ghetta
  7. Email : matteo dot ghetta 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__ = 'Matteo Ghetta'
  18. __date__ = 'March 2017'
  19. __copyright__ = '(C) 2017, Matteo Ghetta'
  20. import warnings
  21. from qgis.core import (QgsProcessingException,
  22. QgsProcessingParameterFeatureSource,
  23. QgsProcessingParameterField,
  24. QgsProcessingParameterEnum,
  25. QgsProcessingParameterFileDestination,
  26. QgsFeatureRequest)
  27. from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
  28. from processing.tools import vector
  29. from qgis.PyQt.QtCore import QCoreApplication
  30. class BoxPlot(QgisAlgorithm):
  31. INPUT = 'INPUT'
  32. OUTPUT = 'OUTPUT'
  33. NAME_FIELD = 'NAME_FIELD'
  34. VALUE_FIELD = 'VALUE_FIELD'
  35. MSD = 'MSD'
  36. def group(self):
  37. return self.tr('Plots')
  38. def groupId(self):
  39. return 'plots'
  40. def __init__(self):
  41. super().__init__()
  42. def initAlgorithm(self, config=None):
  43. self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
  44. self.tr('Input layer')))
  45. self.addParameter(QgsProcessingParameterField(self.NAME_FIELD,
  46. self.tr('Category name field'),
  47. parentLayerParameterName=self.INPUT,
  48. type=QgsProcessingParameterField.Any))
  49. self.addParameter(QgsProcessingParameterField(self.VALUE_FIELD,
  50. self.tr('Value field'),
  51. parentLayerParameterName=self.INPUT,
  52. type=QgsProcessingParameterField.Numeric))
  53. msd = [self.tr('Show Mean'),
  54. self.tr('Show Standard Deviation'),
  55. self.tr('Don\'t show Mean and Standard Deviation')
  56. ]
  57. self.addParameter(QgsProcessingParameterEnum(
  58. self.MSD,
  59. self.tr('Additional Statistic Lines'),
  60. options=msd, defaultValue=0))
  61. self.addParameter(QgsProcessingParameterFileDestination(self.OUTPUT, self.tr('Box plot'), self.tr('HTML files (*.html)')))
  62. def name(self):
  63. return 'boxplot'
  64. def displayName(self):
  65. return self.tr('Box plot')
  66. def processAlgorithm(self, parameters, context, feedback):
  67. try:
  68. # importing plotly throws Python warnings from within the library - filter these out
  69. with warnings.catch_warnings():
  70. warnings.filterwarnings("ignore", category=ResourceWarning)
  71. warnings.filterwarnings("ignore", category=ImportWarning)
  72. import plotly as plt
  73. import plotly.graph_objs as go
  74. except ImportError:
  75. raise QgsProcessingException(QCoreApplication.translate('BoxPlot', 'This algorithm requires the Python “plotly” library. Please install this library and try again.'))
  76. source = self.parameterAsSource(parameters, self.INPUT, context)
  77. if source is None:
  78. raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))
  79. namefieldname = self.parameterAsString(parameters, self.NAME_FIELD, context)
  80. valuefieldname = self.parameterAsString(parameters, self.VALUE_FIELD, context)
  81. output = self.parameterAsFileOutput(parameters, self.OUTPUT, context)
  82. values = vector.values(source, valuefieldname)
  83. x_index = source.fields().lookupField(namefieldname)
  84. x_var = vector.convert_nulls([i[namefieldname] for i in source.getFeatures(QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry).setSubsetOfAttributes([x_index]))], '<NULL>')
  85. msdIndex = self.parameterAsEnum(parameters, self.MSD, context)
  86. msd = True
  87. if msdIndex == 1:
  88. msd = 'sd'
  89. elif msdIndex == 2:
  90. msd = False
  91. data = [go.Box(
  92. x=x_var,
  93. y=values[valuefieldname],
  94. boxmean=msd)]
  95. plt.offline.plot(data, filename=output, auto_open=False)
  96. return {self.OUTPUT: output}