"""Gera o relatório da Fase 1c (série histórica 1996–2014) em PT e EN: ../fase1c/index.html e ../fase1c/en/index.html. Uso: python gerar_fase1c.py (depois de historico.py e tendencias.py; defina CLEDON_DOI para a versão depositada) """ import os import pandas as pd from config import RAIZ, RESULTADOS VERSAO = "1.7" DATAS = {"pt": "13 de novembro de 2026", "en": "November 13, 2026"} BASE = "https://cledon.org" ORCID = "0009-0008-5280-1869" PLANO_COMMIT = "9847190" DOI = os.environ.get("CLEDON_DOI", "").strip() PT = True PER = ["1996-1999", "2000-2004", "2005-2009", "2010-2014", "2015-2019", "2020-2024"] MEIO = {"1996-1999": 1997.5, "2000-2004": 2002, "2005-2009": 2007, "2010-2014": 2012, "2015-2019": 2017, "2020-2024": 2022} SERIES = [("16 municípios", "16 sinais — todos", ("Os 16 municípios", "The 16 municipalities"), "var(--s1)"), ("16 — Sul (PR, SC, RS)", "16 sinais — Sul (PR, SC, RS)", ("Sul (5)", "South (5)"), "var(--s2)"), ("16 — Minas Gerais", "16 sinais — Minas Gerais", ("Minas Gerais (9)", "Minas Gerais (9)"), "var(--s3)"), ("24 áreas", "agrupamentos — todos", ("As 24 áreas", "The 24 areas"), "var(--s4)")] CONJ = {"16 municípios": ("Os 16 municípios", "The 16 municipalities"), "16 — Minas Gerais": ("Minas Gerais (9)", "Minas Gerais (9)"), "16 — Sul (PR, SC, RS)": ("Sul (5)", "South (5)"), "16 — Bahia": ("Bahia (2)", "Bahia (2)"), "24 áreas": ("As 24 áreas", "The 24 areas")} REFS = """
Estudo exploratório — não são conclusões. Descrição ecológica da mortalidade registrada; não indica causa, não permite estimar o risco de uma pessoa e não muda nenhuma recomendação médica. Versão {VERSAO} · {DATAS['pt']}.{doi}
Os 16 municípios com sinal e as 24 áreas de excesso foram identificados com óbitos de 2020–2024. A Fase 1c volta no tempo, com óbitos de 1996 a 2014 que não participaram da seleção, e pergunta se o excesso já existia. O plano de análise foi registrado no git antes dos dados (commit {PLANO_COMMIT}); o relatório incorpora uma revisão técnica assistida por IA (não é revisão independente por pares).
Dados. Óbitos de residentes do SIM/DATASUS de 1996 a 2014 (513 arquivos, todos os estados), com as mesmas regras de agregação das fases anteriores. Nos arquivos antigos o código do município tem 7 dígitos: usamos os 6 primeiros. População por município, sexo e faixa etária dos Censos de 1991, 2000, 2010 e 2022. Esperados pelas taxas do próprio estado no mesmo ano, por sexo e faixa etária. RMP com IC 95% exato e teste de Poisson unilateral.
Correções em relação ao plano (não pré-especificadas). (1) O plano mandava usar, para os {i(len(criados))} municípios criados depois de 1991, a população do Censo seguinte; isso conta duas vezes a área deles em 1996–1999 (ela já estava no município de origem em 1991) e inflava a população do país em cerca de 2%, o que aumentaria artificialmente o excesso. No cálculo principal, 1996–1999 usa a divisão municipal de 2000, ajustada pela variação da população de cada estado, por sexo e faixa, entre 1991 e 2000; o método do plano fica como sensibilidade (seção 6). (2) Um erro de código invertia o valor de p; foi corrigido antes da interpretação e conferido com o teste de Poisson exato. (3) Após uma revisão técnica assistida por IA (não é revisão por pares): análise com áreas mínimas comparáveis (seção 6); redistribuição das causas mal definidas apresentada só de forma descritiva e com tratamento dos estratos sem causa definida (seção 5); tabela de qualidade ampliada aos 14 estados das áreas; resultados gravados sem arredondar as contagens.
Segurança dos dados. Microdados públicos do SIM, sem nome, processados localmente em contagens agregadas por município, ano, sexo, faixa etária e grupo de causa. Nenhum dado individual é publicado; os arquivos originais ficam fora do repositório, com o SHA-256 registrado para reprodução.
RMP do câncer de esôfago por período, em relação ao próprio estado. 1996–2014: esta fase; 2015–2024: Fase 1b (mesmo método, com taxas do estado no mesmo ano). Acima de 1 = mais óbitos que o esperado.
Por região, a história é diferente. No Sul, o excesso é alto e estável desde 1996 (RMP {n(sul96.rmp)} em 1996–1999, {i(sul96.obs)} óbitos). Em Minas Gerais, a RMP de 1996–1999 é {n(mg96.rmp)} (IC {n(mg96.ic95_inf)}–{n(mg96.ic95_sup)}), sem excesso claro. Esses 9 municípios tinham {n(qmg9['1996-1999'], 1)}% de óbitos com causa mal definida no período, contra {n(qmg['1996-1999'], 1)}% no estado; com a redistribuição descritiva dessas causas (seção 5), a RMP passa a {n(mg96r.rmp)}. Na Bahia, os 2 municípios não registraram nenhum óbito por câncer de esôfago em 1996–1999 (esperados {n(ba96.esp, 1)}), com {n(qba2['1996-1999'], 1)}% de causas mal definidas.
Não atenderam ao critério: {sem_rep}. Os dois da Bahia e os dois do Rio Grande do Sul têm poucos óbitos esperados.
Percentual dos óbitos com causa mal definida (CID-10 R00–R99), por período, nos conjuntos analisados e nos 14 estados que têm municípios nas 24 áreas.
{t4}Em áreas com muitas causas mal definidas, parte dos óbitos por câncer de esôfago fica sem diagnóstico registrado. A sensibilidade pré-especificada redistribui os óbitos mal definidos entre as causas definidas, proporcionalmente, por município, ano, sexo e faixa etária. Dos {i(ntot)} óbitos mal definidos de 1996–2014 no país (todos os municípios), {i(nsd)} ({n(100 * nsd / ntot, 1)}%) estavam em estratos sem nenhuma causa definida; para eles usamos a proporção do estado no mesmo ano, sexo e faixa (ajuste feito após a revisão, não pré-especificado; sem ele, esses óbitos ficariam sem alocação).
{t3}Com a redistribuição, os óbitos deixam de ser contagens inteiras e a incerteza da própria redistribuição não entra no cálculo; por isso ela é apresentada só como sensibilidade descritiva (RMP, sem intervalo, valor de p ou classificação de "replica"). A série fica mais estável no tempo. A redistribuição supõe que os óbitos mal definidos se dividem entre as causas como os definidos, o que é uma aproximação.
Desfechos de comparação, 2000–2014.
{t5}No conjunto dos 16, pulmão e outros cânceres ficam abaixo de 1; no Sul, o pulmão fica um pouco acima ({n(pulm_sul)}), bem abaixo do esôfago ({n(eso_sul)}), o que é compatível com o tabaco como exposição comum.
Território constante (áreas mínimas comparáveis; não pré-especificado, feito após a revisão). Quando um município é desmembrado, o território a que se referem óbitos e população muda. {np_} dos 16 municípios perderam território depois de 1991. A sensibilidade territorial prevista no plano (excluir os municípios criados depois de 1991) não resolve isso: os municípios de origem continuam no cálculo e nenhum dos 16 foi criado depois de 1991, de modo que, para os 16, ela repete a análise principal. Por isso usamos as áreas mínimas comparáveis 1991–2010 do IPEA (pacote geobr), que agrupam municípios para manter o mesmo território em todos os anos. Cada unidade passa a ser a união das áreas comparáveis dos seus municípios, com a população interpolada entre os Censos dentro de cada área e os esperados pelas taxas do estado. Uma área comparável que reúne municípios de Minas Gerais e do Espírito Santo foi dividida por estado; os 5 municípios criados em 2013 foram ligados à área do município de origem.
{t6}Os {np_} municípios que perderam território, na área comparável correspondente (2000–2014):
{t7}Com áreas comparáveis, {nam} dos 16 municípios e {naa} das 24 áreas atendem ao critério em 2000–2014 ({nam1} e {naa1} com RMP acima de 1). Série por período com áreas comparáveis:
{t6b}O excesso de mortalidade por câncer de esôfago nesses municípios e áreas não é um fenômeno recente nem uma flutuação de 2020–2024: aparece em dados de 2000 a 2014, que não participaram da seleção, e no Sul desde 1996. Ele é específico do esôfago nos mesmos municípios e se mantém com território constante. A subida da RMP ao longo do tempo deve ser lida com cuidado, porque coincide com a melhora do registro das causas de morte, sobretudo em Minas Gerais e na Bahia. Os resultados reforçam que vale investigar essas regiões, mas continuam sendo uma descrição ecológica: não indicam causa.
Código em {BASE}/codigo: historico.py, gerar_fase1c.py.
Plano: PLANO-fase1c.md (commit {PLANO_COMMIT}). Resultados: fase1c_*.csv na página do mapa e no
depósito do Zenodo.
Em memória de Francisco Cledio Capistrano (F.C.C.).
""" return f"""{ESTILO}Exploratory study — not conclusions. Ecological description of recorded mortality; it does not indicate causation, does not allow estimating any person's risk and does not change any medical recommendation. Version {VERSAO} · {DATAS['en']}.{doi} This is a translation of the Portuguese report; in case of discrepancy, the Portuguese version prevails.
The 16 municipalities with a signal and the 24 excess areas were identified with deaths from 2020–2024. Phase 1c goes back in time, with deaths from 1996 to 2014 that played no part in the selection, and asks whether the excess already existed. The analysis plan was committed to git before the data (commit {PLANO_COMMIT}); the report incorporates an AI-assisted technical review (not independent peer review).
Data. Deaths of residents from SIM/DATASUS (the national mortality information system), 1996 to 2014 (513 files, all states), with the same aggregation rules as in earlier phases. In the older files the municipality code has 7 digits; we use the first 6. Population by municipality, sex and age group from the 1991, 2000, 2010 and 2022 Censuses. Expected deaths from the state's own rates in the same year, by sex and age group. SMR with exact 95% CI and one-sided Poisson test.
Departures from the plan (not pre-specified). (1) For the {i(len(criados))} municipalities created after 1991, the plan specified the population of the following Census; this double-counts their territory in 1996–1999 (it was already part of the municipality of origin in 1991) and inflated the country's population by about 2%, which would artificially increase the excess. In the main analysis, 1996–1999 uses the 2000 municipal division, scaled by each state's population change, by sex and age group, between 1991 and 2000; the plan's method is kept as a sensitivity analysis (section 6). (2) A coding error inverted the p-value; it was fixed before interpretation and checked against the exact Poisson test. (3) After an AI-assisted technical review (not peer review): an analysis with minimum comparable areas (section 6); redistribution of ill-defined causes presented as descriptive only, with treatment of strata with no defined cause (section 5); the quality table extended to the areas' 14 states; results stored without rounding counts.
Data security. Public SIM microdata, with no names, processed locally into counts aggregated by municipality, year, sex, age group and cause group. No individual data are published; the original files are kept outside the repository, with their SHA-256 recorded for reproduction.
Esophageal cancer SMR by period, relative to the state. 1996–2014: this phase; 2015–2024: Phase 1b (same method, with the state's rates in the same year). Above 1 = more deaths than expected.
By region, the story differs. In the South, the excess is high and stable since 1996 (SMR {n(sul96.rmp)} in 1996–1999, {i(sul96.obs)} deaths). In Minas Gerais, the 1996–1999 SMR is {n(mg96.rmp)} (CI {n(mg96.ic95_inf)}–{n(mg96.ic95_sup)}), with no clear excess. These 9 municipalities had {n(qmg9['1996-1999'], 1)}% of deaths with an ill-defined cause in that period, against {n(qmg['1996-1999'], 1)}% in the state; with the descriptive redistribution of these causes (section 5), the SMR becomes {n(mg96r.rmp)}. In Bahia, the 2 municipalities recorded no esophageal cancer deaths in 1996–1999 (expected {n(ba96.esp, 1)}), with {n(qba2['1996-1999'], 1)}% ill-defined causes.
Did not meet the criterion: {sem_rep}. The two in Bahia and the two in Rio Grande do Sul have few expected deaths.
Percentage of deaths with an ill-defined cause (ICD-10 R00–R99), by period, in the sets analysed and in the 14 states with municipalities in the 24 areas.
{t4}In areas with many ill-defined causes, some esophageal cancer deaths go without a recorded diagnosis. The pre-specified sensitivity analysis redistributes ill-defined deaths among the defined causes, proportionally, by municipality, year, sex and age group. Of the {i(ntot)} ill-defined deaths in 1996–2014 in the country (all municipalities), {i(nsd)} ({n(100 * nsd / ntot, 1)}%) were in strata with no defined cause at all; for these we used the state's proportion in the same year, sex and age group (an adjustment made after the review, not pre-specified; without it, these deaths would be left unallocated).
{t3}With redistribution, deaths are no longer whole counts and the uncertainty of the redistribution itself is not part of the calculation; it is therefore presented only as a descriptive sensitivity analysis (SMR, with no interval, p-value or "replicates" classification). The series becomes more stable over time. Redistribution assumes that ill-defined deaths are split among causes in the same way as defined ones, which is an approximation.
Comparison outcomes, 2000–2014.
{t5}For the 16 together, lung and other cancers are below 1; in the South, lung is slightly above ({n(pulm_sul)}), well below the esophagus ({n(eso_sul)}), which is compatible with tobacco as a shared exposure.
Constant territory (minimum comparable areas; not pre-specified, done after the review). When a municipality is split, the territory to which deaths and population refer changes. {np_} of the 16 municipalities lost territory after 1991. The territorial sensitivity analysis in the plan (excluding municipalities created after 1991) does not address this: the municipalities of origin remain in the calculation and none of the 16 was created after 1991, so for the 16 it repeats the main analysis. We therefore used IPEA's 1991–2010 minimum comparable areas (geobr package), which group municipalities so as to keep the same territory in every year. Each unit becomes the union of its municipalities' comparable areas, with population interpolated between Censuses within each area and expected deaths from the state's rates. One comparable area spanning municipalities in Minas Gerais and Espírito Santo was split by state; the 5 municipalities created in 2013 were linked to the area of their municipality of origin.
{t6}The {np_} municipalities that lost territory, in the corresponding comparable area (2000–2014):
{t7}With comparable areas, {nam} of the 16 municipalities and {naa} of the 24 areas meet the criterion in 2000–2014 ({nam1} and {naa1} with an SMR above 1). Series by period with comparable areas:
{t6b}The excess of esophageal cancer mortality in these municipalities and areas is neither a recent phenomenon nor a fluctuation of 2020–2024: it appears in data from 2000 to 2014, which played no part in the selection, and in the South since 1996. It is specific to the esophagus in the same municipalities and holds with constant territory. The rise in the SMR over time should be read with care, because it coincides with improved recording of causes of death, especially in Minas Gerais and Bahia. The results reinforce that these regions are worth investigating, but they remain an ecological description: they do not indicate causation.
Code at {BASE}/codigo: historico.py, gerar_fase1c.py.
Plan: PLANO-fase1c.md (commit {PLANO_COMMIT}). Results: fase1c_*.csv on the map page and in the
Zenodo deposit.
In memory of Francisco Cledio Capistrano (F.C.C.).
""" SECOES = [("resumo", "Resumo", "Abstract"), ("metodo", "Método", "Methods"), ("serie", "Série", "Series"), ("municipios", "Municípios", "Municipalities"), ("areas", "Áreas", "Areas"), ("qualidade", "Qualidade", "Quality"), ("comparacao", "Comparação", "Comparison"), ("interpretacao", "Interpretação", "Interpretation"), ("limitacoes", "Limitações", "Limitations"), ("referencias", "Referências", "References")] def casca(lang): pt = lang == "pt" autor = (f'Autor: Clériston Almeida Capistrano (ORCID {ORCID}) · ' f'pesquisador independente, sem formação na área da saúde · cledon.org') if pt else \ (f'Author: Clériston Almeida Capistrano (ORCID {ORCID}) · ' f'independent researcher with no formal training in health sciences · cledon.org') toc = "".join(f'{b if pt else c}' for a, b, c in SECOES) if pt: return {"HTML_LANG": "pt-BR", "TITLE": "Fase 1c · Série histórica — Cledon", "DESCRIPTION": "Câncer de esôfago no Brasil: o excesso nos 16 municípios e nas 24 áreas já existia de 1996 a 2014?", "NAV_LABEL": "Navegação principal", "NAV": f'O mapaFase 1b' f'CódigoEnglish', "EYEBROW": "Relatório · Fase 1c", "H1": "Câncer de esôfago: o excesso já existia de 1996 a 2014?", "LEAD": "Série histórica de quase 30 anos de mortalidade nos 16 municípios com sinal e nas 24 áreas de excesso. " f'English version.', "AUTHOR": autor, "TOC_LABEL": "Seções", "TOC": toc, "FOOTER": "Cledon · Find Cancer Clues · Iniciativa independente de pesquisa. Este estudo não oferece diagnóstico, " 'tratamento ou orientação médica. contato@cledon.org.', "PAGE": "Página", "OF": "de", "RUNNING": f"Cledon · Fase 1c · v{VERSAO}"} return {"HTML_LANG": "en", "TITLE": "Phase 1c · Historical series — Cledon", "DESCRIPTION": "Esophageal cancer in Brazil: did the excess in the 16 municipalities and 24 areas already exist " "from 1996 to 2014?", "NAV_LABEL": "Main navigation", "NAV": f'The mapPhase 1b' f'CodePortuguês', "EYEBROW": "Report · Phase 1c", "H1": "Esophageal cancer: did the excess already exist from 1996 to 2014?", "LEAD": "A historical series of almost 30 years of mortality in the 16 municipalities with a signal and the 24 " f'excess areas. Versão em português.', "AUTHOR": autor, "TOC_LABEL": "Sections", "TOC": toc, "FOOTER": "Cledon · Find Cancer Clues · Independent research initiative. This study does not provide diagnosis, " 'treatment or medical advice. contato@cledon.org.', "PAGE": "Page", "OF": "of", "RUNNING": f"Cledon · Phase 1c · v{VERSAO}"} def main(): global PT D = dados() modelo = (RAIZ / "modelo_relatorio.html").read_text() for lang, saida in (("pt", RAIZ.parent / "fase1c" / "index.html"), ("en", RAIZ.parent / "fase1c" / "en" / "index.html")): PT = lang == "pt" pagina = modelo.replace("{{CORPO}}", corpo(D)) for k, val in casca(lang).items(): pagina = pagina.replace("{{" + k + "}}", val) assert "{{" not in pagina saida.parent.mkdir(parents=True, exist_ok=True) saida.write_text(pagina) print(f"Fase 1c ({lang}): {saida}") if __name__ == "__main__": main()