Files
2024-06-28 12:23:19 +02:00

216 lines
6.7 KiB
Python

from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import (QgsProcessing,
QgsProcessingAlgorithm,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterFileDestination,
QgsProcessingParameterField,
QgsProcessingParameterString,
QgsProcessingParameterNumber,
QgsProcessingParameterBoolean)
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import math
class matplotlibScat(QgsProcessingAlgorithm):
INPUT = 'INPUT'
OUTPUT = 'OUTPUT'
X_VALUES = 'X_VALUES'
Y_VALUES = 'Y_VALUES'
X_MAX = 'X_MAX'
Y_MAX = 'Y_MAX'
FLIP_X = 'FLIP_X'
FLIP_Y = 'FLIP_Y'
COLOR = 'COLOR'
TITLE = 'TITLE'
X_LABEL = 'X_LABEL'
Y_LABEL = 'Y_LABEL'
def tr(self, string):
return QCoreApplication.translate('Processing', string)
def createInstance(self):
return matplotlibScat()
def name(self):
return 'Scatter Plot'
def displayName(self):
return self.tr('Scatter Plot')
def group(self):
return self.tr('matplotlib vector')
def groupId(self):
return 'matplotlib vector'
def shortHelpString(self):
return self.tr("Generates a scatter plot for two selected numeric attributes from an input layer.")
def initAlgorithm(self, config=None):
self.addParameter(
QgsProcessingParameterFeatureSource(
self.INPUT,
self.tr('Input layer'),
[QgsProcessing.TypeVectorAnyGeometry]
)
)
self.addParameter(QgsProcessingParameterFileDestination(
'OUTPUT',
self.tr('Plot Output File'),
'PNG Files (*.png)'
)
)
self.addParameter(
QgsProcessingParameterField(
self.X_VALUES,
self.tr('X Values'),
None,
self.INPUT,
QgsProcessingParameterField.Numeric
)
)
self.addParameter(
QgsProcessingParameterField(
self.Y_VALUES,
self.tr('Y Values'),
None,
self.INPUT,
QgsProcessingParameterField.Numeric
)
)
self.addParameter(
QgsProcessingParameterNumber(
self.X_MAX,
self.tr('X Max'),
type=QgsProcessingParameterNumber.Double,
optional=True
)
)
self.addParameter(
QgsProcessingParameterNumber(
self.Y_MAX,
self.tr('Y Max'),
type=QgsProcessingParameterNumber.Double,
optional=True
)
)
self.addParameter(
QgsProcessingParameterBoolean(
self.FLIP_X,
self.tr('Flip X Axis'),
defaultValue=False
)
)
self.addParameter(
QgsProcessingParameterBoolean(
self.FLIP_Y,
self.tr('Flip Y Axis'),
defaultValue=False
)
)
self.addParameter(
QgsProcessingParameterString(
self.COLOR,
self.tr('Color'),
defaultValue='blue'
)
)
self.addParameter(
QgsProcessingParameterString(
self.TITLE,
self.tr('Title'),
defaultValue=' '
)
)
self.addParameter(
QgsProcessingParameterString(
self.X_LABEL,
self.tr('X Label'),
defaultValue=' '
)
)
self.addParameter(
QgsProcessingParameterString(
self.Y_LABEL,
self.tr('Y Label'),
defaultValue=' '
)
)
def processAlgorithm(self, parameters, context, feedback):
source = self.parameterAsSource(parameters, self.INPUT, context)
x_field = self.parameterAsString(parameters, self.X_VALUES, context)
y_field = self.parameterAsString(parameters, self.Y_VALUES, context)
x_max = self.parameterAsDouble(parameters, self.X_MAX, context)
y_max = self.parameterAsDouble(parameters, self.Y_MAX, context)
flip_x = self.parameterAsBool(parameters, self.FLIP_X, context)
flip_y = self.parameterAsBool(parameters, self.FLIP_Y, context)
color = self.parameterAsString(parameters, self.COLOR, context)
title = self.parameterAsString(parameters, self.TITLE, context)
x_label = self.parameterAsString(parameters, self.X_LABEL, context)
y_label = self.parameterAsString(parameters, self.Y_LABEL, context)
output = self.parameterAsFileOutput(parameters, self.OUTPUT, context)
feedback.pushInfo(f"Source: {source}")
feedback.pushInfo(f"x_field: {x_field}")
feedback.pushInfo(f"y_field: {y_field}")
feedback.pushInfo(f"x_max: {x_max}")
feedback.pushInfo(f"y_max: {y_max}")
feedback.pushInfo(f"flip_x: {flip_x}")
feedback.pushInfo(f"flip_y: {flip_y}")
feedback.pushInfo(f"title: {title}")
feedback.pushInfo(f"x_label: {x_label}")
feedback.pushInfo(f"y_label: {y_label}")
feedback.pushInfo(f"output: {output}")
x_values = []
y_values = []
for feature in source.getFeatures():
try:
x = float(feature[x_field])
y = float(feature[y_field])
if not (math.isnan(x) or math.isnan(y)):
x_values.append(x)
y_values.append(y)
except Exception as e:
continue
feedback.pushInfo(f"x_values: {x_values}")
feedback.pushInfo(f"y_values: {y_values}")
try:
plt.scatter(x_values, y_values, color=color)
plt.xlim(0, x_max)
plt.ylim(0, y_max)
if flip_x:
plt.gca().invert_xaxis()
if flip_y:
plt.gca().invert_yaxis()
plt.title(title)
plt.xlabel(x_label)
plt.ylabel(y_label)
plt.savefig(output)
plt.close()
feedback.pushInfo(f"Scatter plot saved to {output}")
return {self.OUTPUT: output}
except Exception as e:
feedback.reportError(f"Error: {e}")
return {}