BOXES / boxes_2026.py
ESJL's picture
Create boxes_2026.py
0681b2e verified
import openpyxl
import xgboost as xgb
import gradio as gr
import joblib
import pandas as pd
import numpy as np
import seaborn as sns
import statsmodels.api as sm
import matplotlib.pyplot as plt
import io
from sklearn.preprocessing import MinMaxScaler
from reportlab.lib import colors
from reportlab.lib.units import inch
from reportlab.lib.pagesizes import A4, landscape
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.pdfgen.canvas import Canvas
from reportlab.platypus import SimpleDocTemplate, Spacer, Image, Frame, PageTemplate, BaseDocTemplate, Table, Paragraph, NextPageTemplate, PageBreak
# --- Função de Geração do Relatório PDF ---
def get_report(ANO_CONST, RH, X, Y, ATOTAL, ANO_2020, ANO_2021, ANO_2022, ANO_2023, ANO_2024, ANO_2025, pred):
# Define the page size
pagesize = A4
def on_page(canvas, doc):
page_num = canvas.getPageNumber()
canvas.drawCentredString(pagesize[0] / 2, 50, str(page_num))
def on_page_landscape(canvas, doc):
return on_page(canvas, doc, pagesize=landscape(A4))
padding = dict(
leftPadding=72,
rightPadding=72,
topPadding=72,
bottomPadding=18)
portrait_frame = Frame(0, 0, *A4, **padding)
landscape_frame = Frame(0, 0, *landscape(A4), **padding)
portrait_template = PageTemplate(id='portrait',
frames=portrait_frame,
onPage=on_page,
pagesize=A4)
landscape_template = PageTemplate(id='landscape',
frames=landscape_frame,
onPage=on_page_landscape,
pagesize=landscape(A4))
doc = BaseDocTemplate('report.pdf',
pageTemplates=[portrait_template,landscape_template])
styles = getSampleStyleSheet()
story = [
# Image('DAI.png', width=6.4 * inch, height=1.28 * inch), # Certifique-se que a imagem existe ou comente
Spacer(1, 36),
Paragraph('Modelo para Boxes de Estacionamento - XGBoost Regressor - 2026', styles['Heading1']),
Paragraph('Parâmetros do cálculo', styles['Heading2']),
Paragraph(f"Ano de Construção (Conforme Cadastro Imobiliário): {ANO_CONST}", styles['Normal']),
Paragraph(f"Região Homogênea: {RH}", styles['Normal']),
Paragraph(f"Coordenada X (TM-POA): {X}", styles['Normal']),
Paragraph(f"Coordenada Y (TM-POA): {Y}", styles['Normal']),
Paragraph(f"Área Total (Conforme Cadastro Imobiliário): {ATOTAL}", styles['Normal']),
Paragraph(f"Ano 2020 - Exercício Fiscal 2021: {'Sim' if ANO_2020 else 'Não'}", styles['Normal']),
Paragraph(f"Ano 2021 - Exercício Fiscal 2022: {'Sim' if ANO_2021 else 'Não'}", styles['Normal']),
Paragraph(f"Ano 2022 - Exercício Fiscal 2023: {'Sim' if ANO_2022 else 'Não'}", styles['Normal']),
Paragraph(f"Ano 2023 - Exercício Fiscal 2024: {'Sim' if ANO_2023 else 'Não'}", styles['Normal']),
Paragraph(f"Ano 2024 - Exercício Fiscal 2025: {'Sim' if ANO_2024 else 'Não'}", styles['Normal']),
Paragraph(f"Ano 2025 - Exercício Fiscal 2026: {'Sim' if ANO_2025 else 'Não'}", styles['Normal']),
Spacer(1, 36),
Paragraph('Resultado', styles['Heading1']),
Paragraph('Valor do imóvel (R$)', styles['Heading2']),
Paragraph(f"R$ {round(pred[0][0] * ATOTAL, -2)}", styles['Normal']),
]
doc.build(story)
# --- Função de Execução do Modelo ---
def execute(ANO_CONST, RH, X, Y, ATOTAL, ANO_2020, ANO_2021, ANO_2022, ANO_2023, ANO_2024, ANO_2025):
# Criação do DataFrame incluindo a nova variável ANO_2025
df = pd.DataFrame.from_dict({'ANO_CONST': [ANO_CONST],
'RH': [RH],
'X': [X],
'Y': [Y],
'ATOTAL': np.log(ATOTAL),
'ANO_2020': 1 if ANO_2020 else 0,
'ANO_2021': 1 if ANO_2021 else 0,
'ANO_2022': 1 if ANO_2022 else 0,
'ANO_2023': 1 if ANO_2023 else 0,
'ANO_2024': 1 if ANO_2024 else 0,
'ANO_2025': 1 if ANO_2025 else 0,
})
print("Inputs Recebidos:")
print(df)
# ATENÇÃO: Os arquivos .save e .model abaixo devem ter sido atualizados/treinados
# contemplando a coluna ANO_2025. Caso contrário, ocorrerá erro de shape.
input_scaler = joblib.load("dados/boxes/input_scaler_boxes_2025_VU.save")
# Transformação
df_transformed = input_scaler.transform(df)
# Definição das colunas para o DMatrix (incluindo a nova)
cols = ['ANO_CONST', 'RH', 'X', 'Y', 'ATOTAL', 'ANO_2020', 'ANO_2021', 'ANO_2022', 'ANO_2023', 'ANO_2024', 'ANO_2025']
aval = pd.DataFrame(df_transformed, columns=cols)
dmatrix_data = xgb.DMatrix(aval)
# Carregamento do Modelo
loaded_model = xgb.Booster()
loaded_model.load_model("dados/boxes/boxes_2020_2026.model") # Verificar se o nome do arquivo mudou para 2026
# Predição
pred = loaded_model.predict(dmatrix_data)
# Escala de saída
output_scaler = joblib.load("dados/boxes/output_scaler_boxes_2025_VU.save")
pred = output_scaler.inverse_transform(np.array(pred).reshape(-1,1))
pred = np.exp(pred)
# Gerar Relatório
get_report(ANO_CONST, RH, X, Y, ATOTAL, ANO_2020, ANO_2021, ANO_2022, ANO_2023, ANO_2024, ANO_2025, pred)
return f"""R${round(pred[0][0] * ATOTAL, -2)}""", 'report.pdf'
# --- Configuração dos Inputs do Gradio ---
def load_inputs():
ANO_CONST = gr.Number(value=2020, label='Ano de Construção (Conforme Cadastro Imobiliário)')
RH = gr.Number(value=120, label='Região Homogênea')
X = gr.Number(label='Coordenada X (TM-POA)', value=281554.)
Y = gr.Number(label='Coordenada Y (TM-POA)', value=1675418.)
ATOTAL = gr.Number(label='Área Total (Conforme Cadastro Imobiliário)', value=12.)
# Checkboxes para os anos dummies
ANO_2020 = gr.Checkbox(label='Ano 2020 - Carga Geral 2021', value=False)
ANO_2021 = gr.Checkbox(label='Ano 2021 - Carga Geral 2022', value=False)
ANO_2022 = gr.Checkbox(label='Ano 2022 - Carga Geral 2023', value=False)
ANO_2023 = gr.Checkbox(label='Ano 2023 - Carga Geral 2024', value=False)
ANO_2024 = gr.Checkbox(label='Ano 2024 - Carga Geral 2025', value=False)
ANO_2025 = gr.Checkbox(label='Ano 2025 - Carga Geral 2026', value=True) # Definido como True por padrão para o modelo atual
return [ANO_CONST, RH, X, Y, ATOTAL, ANO_2020, ANO_2021, ANO_2022, ANO_2023, ANO_2024, ANO_2025]
# --- Configurações da Interface ---
title = 'Boxes - XGBoost Regressor - 2026'
description = f"""
# <p style="text-align: center;">Modelo para Boxes de Estacionamento - XGBoost Regressor - 2026</p>
<p style="text-align: center;">Dados efetivamente utilizados, referentes aos anos 2019 a 2025.</p>
<hr style="color: #333; background-color: #333; height: 1px; border: none;">
"""