0

I created a model that combines two vector layers and outputs a single layer with aggregated data. I have a Python script that calculates the Chi-square, and I would like it to be executed at the end of the model's execution.

How do I incorporate the Chi-square code into the modeler?

script Chi-square:

import numpy as np
from scipy.stats import chisquare, norm
from qgis.gui import QgsFieldComboBox, QgsDoubleSpinBox
from qgis.PyQt.QtWidgets import QInputDialog, QMessageBox
# Função para calcular os valores críticos com base no novo valor de alfa corrigido
def calcular_valores_criticos(alfa_corrigido):
 # Calcular os valores críticos da distribuição normal padrão
 limite_superior = norm.ppf(1 - alfa_corrigido / 2)
 limite_inferior = norm.ppf(alfa_corrigido / 2)
 return limite_superior, limite_inferior
# Função para realizar o teste qui-quadrado de aderência com correção de Bonferroni
def qui_quadrado_aderencia_qgis(camada, campo_esperado, campo_observado, alfa):
 # Verificar se a camada está carregada
 if not camada:
 print("Camada inválida. Verifique se uma camada está ativa.")
 return
 # Inicializar listas para valores esperados e observados
 valores_esperados = []
 valores_observados = []
 # Acessar os dados da camada e extrair os valores esperados e observados
 for feature in camada.getFeatures():
 valor_esperado = feature[campo_esperado]
 valor_observado = feature[campo_observado]
 if isinstance(valor_esperado, (int, float)) and isinstance(valor_observado, (int, float)):
 valores_esperados.append(float(valor_esperado))
 valores_observados.append(float(valor_observado))
 # Executar o teste qui-quadrado de aderência
 chi2, p_valor = chisquare(valores_observados, f_exp=valores_esperados)
 # Calcular os resíduos padronizados ajustados
 res_padronizados = (np.array(valores_observados) - np.array(valores_esperados)) / np.sqrt(valores_esperados)
 # Aplicar a correção de Bonferroni ao valor de alfa
 p_valor_corrigido = p_valor * len(valores_esperados) # Número de testes multiplicado pelo p-valor original
 alfa_corrigido = alfa / len(valores_esperados)
 # Calcular os valores críticos com base no novo valor de alfa corrigido
 limite_superior, limite_inferior = calcular_valores_criticos(alfa_corrigido)
 # Imprimir os resultados
 print("Estatística qui-quadrado:", chi2)
 print("Valor-p:", p_valor)
 print("Valor-p corrigido (Bonferroni):", p_valor_corrigido)
 print("Resíduos Padronizados:")
 print(res_padronizados)
 print(f"Valores críticos para alfa corrigido ({alfa_corrigido}):")
 print(f"Limite Superior: {limite_superior}")
 print(f"Limite Inferior: {limite_inferior}")
 # Interpretar o resultado com a correção de Bonferroni
 if p_valor_corrigido < alfa_corrigido:
 print("Rejeitar a hipótese nula: A distribuição do fenômeno analisado não possui carácter aleatório (com correção de Bonferroni).")
 else:
 print("Falha em rejeitar a hipótese nula: A distribuição do fenômeno analisado possui carácter aleatório (com correção de Bonferroni).")
# Obter a camada ativa no QGIS
camada_ativa = iface.activeLayer()
# Usar QInputDialog para obter os campos de atributos e o valor de alfa
campo_esperado, ok = QInputDialog.getItem(None, "Campo de Valores Esperados", "Selecione o campo de valores esperados:",
 [field.name() for field in camada_ativa.fields()])
if not ok:
 QMessageBox.critical(None, "Erro", "Seleção de campo de valores esperados cancelada.")
else:
 campo_observado, ok = QInputDialog.getItem(None, "Campo de Valores Observados", "Selecione o campo de valores observados:",
 [field.name() for field in camada_ativa.fields()])
 if not ok:
 QMessageBox.critical(None, "Erro", "Seleção de campo de valores observados cancelada.")
 else:
 alfa, ok = QInputDialog.getDouble(None, "Valor de Alfa", "Digite o valor de alfa (nível de significância):", 0.05, 0, 1, 6)
 if ok:
 # Chamar a função qui_quadrado_aderencia_qgis
 qui_quadrado_aderencia_qgis(camada_ativa, campo_esperado, campo_observado, alfa)
PolyGeo
65.5k29 gold badges115 silver badges349 bronze badges
asked Jan 10, 2024 at 15:12
2
  • I don't believe it is possible, but you could export your model, as it is with the merge of 2 vector layers), to a Python script algorithm (Model -> Export -> Export as Python Script...) and edit that script to include your Chi-square code. Commented Jan 11, 2024 at 7:22
  • Or as the deleted answer proposed (sorry answerer, I misread it), you can turn your Chi-square code into a Processing Algorithm and insert it inside your model. Commented Jan 11, 2024 at 8:53

1 Answer 1

-1

It is possible to include your script into a model. I would not export the whole model and include your script. An other way is, to make a seperate process and include the process in a model. You have to get rid of all QInputDialogs and integrate inputs into the processing script. It then looks like the following script. This will produce an Inputdialog for the algorithm. You have to put your logic then in the def processAlgorithm function.

from qgis.core import QgsProcessing
from qgis.core import QgsProcessingAlgorithm
from qgis.core import QgsProcessingMultiStepFeedback
from qgis.core import QgsProcessingParameterField
from qgis.core import QgsProcessingParameterVectorLayer
from qgis.core import QgsProcessingParameterFeatureSink
import processing
import numpy as np
from scipy.stats import chisquare, norm
#Função para calcular os valores críticos com base no novo valor de alfa corrigido
def calcular_valores_criticos(alfa_corrigido):
 # Calcular os valores críticos da distribuição normal padrão
 limite_superior = norm.ppf(1 - alfa_corrigido / 2)
 limite_inferior = norm.ppf(alfa_corrigido / 2)
 return limite_superior, limite_inferior
class p_chisquare(QgsProcessingAlgorithm):
 def initAlgorithm(self, config=None):
 self.addParameter(QgsProcessingParameterVectorLayer('camada_ativa', 'camada_ativa', types=[QgsProcessing.TypeVectorAnyGeometry], defaultValue=None)) 
 self.addParameter(QgsProcessingParameterField('campo_observado', 'campo_observado', type=QgsProcessingParameterField.Any, parentLayerParameterName='camada_ativa', allowMultiple=False, defaultValue=None))
 self.addParameter(QgsProcessingParameterField('campo_esperado', 'campo_esperado', type=QgsProcessingParameterField.Any, parentLayerParameterName='camada_ativa', allowMultiple=False, defaultValue=None))
 self.addParameter(QgsProcessingParameterFeatureSink('Result', 'Result', type=QgsProcessing.TypeVectorPolygon, createByDefault=True, supportsAppend=True, defaultValue=None))
 def processAlgorithm(self, parameters, context, model_feedback):
 # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the
 # overall progress through the model
 feedback = QgsProcessingMultiStepFeedback(1, model_feedback)
 results = {}
 outputs = {}
 
 #-->> Here comes your algorithm
 return results
 def name(self):
 return 'p_chisquare'
 def displayName(self):
 return 'chisquare'
 def group(self):
 return ''
 def groupId(self):
 return ''
 def createInstance(self):
 return p_chisquare()
answered Jan 11, 2024 at 8:14
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.