Pipeline em Python para unificar mapeamentos geolĂłgicos, classificar por grupos coerentes (a partir de SIGLA), gerar paletas e QMLs do QGIS com mistura de cores ponderada por área, e produzir legendas JSON ordenadas por tempo geolĂłgico. Inclui utilitários de escala cartográfica e poda de polĂgonos pequenos em função da escala do layout — e um mĂłdulo de plotagem para gerar mapas prontos direto do GeoDataFrame.
TL;DR: junte seus shapefiles, classifique por grupos (
coarse_grp), recorte por bbox, dissolva, exporte QML + JSON de legenda… ou pule direto para a plotagem com uma legenda simplificada. Sem derramar café nos QMLs.
geomageddon/
├── code/
│ ├── geomageddon.py # classe e pipeline principais (GeoSiglaStyler)
│ └── plotagem.py # funções de plotagem (matplotlib/geopandas)
├── notebooks/
│ └── geological_map.ipynb # notebook de testes/exemplos
└── data/ # dados de entrada/saĂda organizados por estado
├── sig_geologia_estado_do_parana_vf/
├── sig_mato_grosso_do_sul/
├── sig_minas_gerais/
├── sig_rio_grande_do_sul/
├── sig_santa_catarina/
└── sig_sao_paulo/
Cada subdiretĂłrio de data contĂ©m camadas de um SIG de geologia regional distribuĂdo pela CPRM/SGB (apenas para exemplo). Verifique a licença/uso dos dados na fonte.
-
Merge de mĂşltiplos
GeoDataFrames com alinhamento automático de CRS. -
Classificação a partir de
SIGLA_UNID(ou equivalente) gerando:idade_code,greek,stemecoarse_grp;- lógica de “dominó” com EON e ERA →
macro_eraconsistente; - fusão opcional por NOME_UNIDA (puxa para o grupo dominante por área/contagem);
- opção de colapsar todo o Cenozóico em um único grupo.
-
Cores inteligentes:
- Mistura ponderada por área a partir de QML(s) de referência (SIGLA → cor);
- Fallback por CLASSE_ROC e CLASSE_R_1 (também ponderado por área);
- Fallback por idade (paleta geocronolĂłgica);
- Jitter suave para desempatar cores idĂŞnticas.
-
Exportação de QML (renderer categorized) e JSON de auditoria das cores.
-
Legendas JSON (completo e simplificado) ordenadas por idade (opções youngest‑first ou oldest‑first).
-
Recorte por bbox em WGS84 com fallback robusto.
-
Escala cartográfica a partir da largura da figura (mm/cm/in/px) com arredondamento nice.
-
Poda de polĂgonos pequenos com base na área fĂsica em mm² no layout (cKDTree/STRtree/sjoin).
-
Plotagem pronta: gere figuras com
plotagem.pyusando a legenda simplificada.
Recomendado Python ≥ 3.10.
Clone o repositĂłrio e instale as dependĂŞncias com conda ou pip:
git clone https://github.com/<usuario>/geomageddon.git
cd geomageddon
conda env create -f environment.yml
conda activate geomageddonOu instale manualmente:
pip install geopandas shapely numpy pandas scipy matplotlibVocĂŞ nĂŁo precisa do QGIS para rodar o pipeline, apenas para visualizar os
.qmlexportados.
A classe assume, por padrĂŁo, nomes de colunas comuns em bases da CPRM. Personalize no __init__ se os seus forem diferentes:
| Papel | Coluna padrĂŁo |
|---|---|
| Sigla da unidade | SIGLA_UNID |
| Nome da unidade | NOME_UNIDA |
| EON mĂnimo/máximo | EON_IDAD_1, EON_IDAD_M |
| ERA mĂnima/máxima | ERA_MINIMA, ERA_MAXIMA |
| Hierarquia | HIERARQUIA |
| Classe ROC | CLASSE_ROC |
| Classe R1 | CLASSE_R_1 |
| Idade min/max (Ma) | IDADE_MIN, IDADE_MAX |
CRS: para cálculos de área (mistura ponderada e poda), forneça um CRS em metros via
area_crs(ex.: Albers Equal Area). Sem CRS, o cĂłdigo cai em pesos iguais (avisa no metadata).
import geopandas as gpd
from code.geomageddon import GeoSiglaStyler # classe principal
# 1) Dados de entrada
br_pr = gpd.read_file("/caminho/br_pr.shp")
br_sc = gpd.read_file("/caminho/br_sc.shp")
sty = GeoSiglaStyler(
area_crs="EPSG:5880", # Albers Brasil (exemplo) ou outro CRS métrico
area_weighting=True, # mistura de cores ponderada por área
)
# 2) Combinar e classificar
base = sty.combine_and_classify(gdfs=[br_pr, br_sc], enforce_mode="flag")
# 3) Recorte (opcional)
sty.clip_to_bbox(base, {
"min_lon": -54, "max_lon": -45,
"min_lat": -30, "max_lat": -22,
})
# 4) Dissolver por grupo coerente
parts = sty.dissolve_by_attr(attr="coarse_grp")
# 5) Cores + QML (usa base pré-dissolve para misturas)
cmap, audit = sty.build_color_map_from(gdf=sty.g_clipped, attr="coarse_grp")
sty.export_qml("out/mantiqueira.qml", gdf=parts, source_gdf_for_mix=sty.g_clipped)
# 6) Legendas (completa e simplificada)
full_legend = sty.build_legend_dict(parts)
sty.export_legend_json("out/legend.full.json", full_legend)
simp_legend = sty.simplified_legend_dict(parts, youngest_first=True)
sty.export_legend_json("out/legend.simple.json", simp_legend)
# 7) (Opcional) Poda por escala e salvar shapefile
parts_pruned = sty.cull_small_parts_by_scale(parts, min_area_mm2=1.0)
sty.save_shp(parts_pruned, "out/mantiqueira_dissolved.shp")Abra o mantiqueira.qml no QGIS e aplique na camada dissolvida. Ou siga para a seção de plotagem para gerar a figura direto em Python.
A escolha da cor do grupo (grp_color) segue prioridades:
- QML(s) de referência (SIGLA → #RRGGBB). O método seleciona automaticamente o atributo mais coberto por área (tipicamente
sigla) e mistura as cores das SIGLAs do grupo; - CLASSE_ROC (mistura ponderada por área);
- CLASSE_R_1 (mistura ponderada por área);
- Idade (paleta geocronolĂłgica embutida);
- Jitter sutil para desempatar grupos que ainda ficaram com a mesma cor.
O peso de cada categoria é calculado por área no CRS métrico (ou pesos iguais, na falta de CRS). Configure
area_crse mantenha geometrias válidas.
Ao gerar o QML via make_qml/export_qml, um arquivo *.audit.json é salvo com detalhes por grupo, incluindo mixes por SIGLA/ROC/R1 e instantâneos das rodadas de desempate por cor.
O módulo plotagem.py fornece funções utilitárias para criar figuras diretamente a partir do GeoDataFrame. A função principal é:
plot_geodf_by_simplified_legend(gdf, legend, *, group_attr="coarse_grp", title=None, projection="EPSG:4674", data_crs="EPSG:4674", figure_path=None, show_states=False, states_resolution="50m", legend_outside=True, legend_cols=4, legend_h="right", legend_v="up")
- Entrada
legend: use exatamente o dicionário retornado porGeoSiglaStyler.simplified_legend_dict(...). - CRS:
projectionedata_crspermitem projetar/no reprojetar os dados para a figura. - Legenda: pode ser externa (
legend_outside=True), com colunas configuráveis e ancoragem horizontal/vertical. - SaĂda: se
figure_pathfor fornecido, salva a figura (ex.: PNG); caso contrário, exibe em tela.
from code.geomageddon import GeoSiglaStyler
from code import plotagem as plot
# Prepare dados e cores (como no exemplo rápido)
cmap, audit = sty.build_color_map_from(gdf=sty.g_clipped, attr="coarse_grp")
simp = sty.simplified_legend_dict(gdf=sty.g_clipped)
plot.plot_geodf_by_simplified_legend(
sty.g_clipped,
simp,
group_attr="coarse_grp",
title="Mapa litolĂłgico",
projection="EPSG:4674",
data_crs="EPSG:4674",
figure_path="data/out/g_diss.png",
show_states=False,
states_resolution="50m",
legend_outside=True,
legend_cols=4,
legend_h="right", # "left" | "right"
legend_v="up" # "up" | "down"
)O notebook
notebooks/geological_map.ipynbtraz um fluxo completo (do merge Ă plotagem) usando shapefiles de exemplo da CPRM.
Há duas formas principais:
- Completa (
build_legend_dict) — estrutura hierárquica por Pré‑cambriano/Fanerozoico e sub‑blocos (Arqueano/Proterozoico/Paleozoico/Mesozóico/Cenozoico), com itens (sigla, nome, hierarquia) e envelope de idades do grupo. - Simplificada (
simplified_legend_dict) — apenas os grupos comcolor,idade_max,idade_min, organizados temporalmente. Ideal para construir uma legenda compacta no layout e para dirigir a plotagem viaplotagem.py.
Salve qualquer uma com export_legend_json("legend.json", data).
-
width_to_scale(...)calcula 1:N a partir da largura da figura (mm/cm/in/px), margem e CRS. Usa arredondamento nice (1, 2, 2.5, 5 Ă— 10^k). -
cull_small_parts_by_scale(...)remove partes cuja área fĂsica (na escala corrente) seja menor quemin_area_mm2(padrĂŁo 1 mm²), reagregando cada peça ao vizinho mais apropriado (que toca ou Ă© mais prĂłximo, desempate por maior área).- Rápido com SciPy cKDTree; fallbacks: Shapely STRtree,
sjoin,sjoin_nearest.
- Rápido com SciPy cKDTree; fallbacks: Shapely STRtree,
Requer CRS mĂ©trico. Se indisponĂvel, Ă© levantada uma exceção explicativa.
Principais métodos (nomes abreviados; veja docstrings no código para detalhes):
-
Carga e pré‑processo
merge(gdfs)— concatena GDFs alinhando CRS.combine_and_classify(gdfs|in_gdf, ..., enforce_mode)— geracoarse_grp,macro_erae afins.clip_to_bbox(gdf, {min_lon,max_lon,min_lat,max_lat})— recorta em WGS84 (fallback robusto).
-
Dissolve e atributos
dissolve_by_attr(gdf, attr="coarse_grp")— dissolve preservando textos únicos e regras de idade/EON/ERA.
-
Cores, QML e legendas
build_color_map_from(gdf, attr="coarse_grp")— cria mapa de cores e auditoria.make_qml(gdf, qml_path, attr, source_gdf_for_mix)/export_qml(...)— salva.qml(renderer categorized).build_legend_dict(gdf)/simplified_legend_dict(gdf, youngest_first=True)— dicionários de legenda.export_legend_json(path, data=None)— salva JSON de legenda.
-
Escala e poda
width_to_scale(gdf, fig_width, width_unit, ...)— retornaNou(N, meta).cull_small_parts_by_scale(gdf, min_area_mm2=1.0, ...)— remove partes pequenas com união guiada por vizinhança.
-
IO
save_shp(gdf, out_path)— exporta ESRI Shapefile com strings normalizadas.
- Instale SciPy para acelerar a poda por KDTree (
pip install scipy). - Se a base for muito grande, ative o
clip_to_bboxantes de dissolver/colorir. - Ajuste
area_weighting=Falsepara testes rápidos (mistura por contagem em vez de área). - Ajuste
auto_cull_small_partsemin_area_mm2conforme a escala alvo do layout.
- “gdf.crs ausente; pesos=1.0”: defina
area_crsno construtor ou atribua um CRS projetado ao GDF antes dos cálculos. - “Não dá para podar por escala sem CRS métrico”: a poda exige áreas em m²; forneça
area_crs. - QML sem cores: verifique se o(s) QML(s) de referência foram carregados (padrão: auto‑busca por
*lito.qmlem/mnt/data). Carregue manualmente:load_sigla_qml(["/caminho/a.qml"]). - Campos ausentes: personalize os nomes no
__init__(ex.:roc_field="CLASSE_ROC").
O QML gerado usa renderer-v2 type="categorizedSymbol" e propriedades padrão de preenchimento/borda. Testado com QGIS 3.28+ (formato estável). Caso seu estilo use Option name="color", o parser também reconhece esse padrão.
MIT License. Use, modifique e destrua polĂgonos livremente.
Sugestões e PRs são bem‑vindos. Se algo quebrar, culpe a geometria inválida… ou o Cambriano C_CORTADO_, que sempre aparece onde menos se espera.