Guia de Migração v1.x para v2.x

Este guia descreve as mudanças necessárias para migrar código e fluxos de trabalho da série de versões v1.x para a série v2.x do sintetizador-newave.

Aviso

A versão v2.0.0 introduziu mudanças incompatíveis com versões anteriores em diversas áreas. Código que consome os arquivos de saída da série v1.x precisará ser atualizado. Leia este guia na íntegra antes de iniciar a migração.

Aviso

Não existem scripts de migração automática. Todas as adaptações devem ser realizadas manualmente no código downstream que consome as saídas do sintetizador.

Resumo das Mudanças

A tabela abaixo lista as categorias de mudanças incompatíveis introduzidas na v2.0.0.

Mudanças Incompatíveis na v2.0.0

Categoria

Descrição

Impacto

Versão do Python

Suporte ao Python 3.8 descontinuado. Mínimo obrigatório: Python >= 3.10.

Alto

Nomenclatura das colunas

Todas as colunas dos DataFrames foram renomeadas para snake_case.

Alto

Indexação de entidades

Entidades indexadas por código numérico ao invés de nome textual (ex.: usina -> codigo_usina).

Alto

Formato dos arquivos Parquet

Compressão alterada de gzip para snappy (padrão Arrow). Extensão dos arquivos passa de .parquet.gz para .parquet.

Alto

Reestruturação dos Patamares

Colunas patamar e duracao_patamar adicionadas em todas as sínteses. patamar = 0 representa o valor médio do estágio.

Alto

Arquivos de estatísticas

Novas saídas ESTATISTICAS_*.parquet com estatísticas pré-calculadas por variável e entidade.

Médio

Arquivos de metadados

Novas saídas METADADOS_*.parquet com informações sobre as sínteses realizadas.

Médio

Sínteses de violação removidas

Sínteses específicas de violações foram removidas e substituídas pelas colunas limite_inferior e limite_superior nos dados brutos.

Alto

Versão do Python

O suporte ao Python 3.8 foi descontinuado na v2.0.0. A versão mínima suportada passou a ser Python >= 3.10, que é a versão mínima garantida nos ambientes de CI e com reprodutibilidade assegurada.

v1.x (antes):

Python >= 3.8 suportado

v2.x (depois):

Python >= 3.10 obrigatório

Verifique sua versão instalada com:

$ python --version

Caso necessário, atualize o ambiente antes de instalar a v2.x:

$ pip install sintetizador-newave>=2.0.0

Nomenclatura das Colunas

Todas as colunas dos DataFrames de saída foram padronizadas para snake_case na v2.0.0. Nomes de colunas com letras maiúsculas, acentos ou espaços foram substituídos por equivalentes em minúsculas com underscores.

v1.x (antes):

>>> import pandas as pd
>>> df = pd.read_parquet("sintese/CMO_SBM.parquet")
>>> df.columns.tolist()
['Submercado', 'Estagio', 'Data', 'Cenario', 'Valor']

v2.x (depois):

>>> import polars as pl
>>> df = pl.read_parquet("sintese/CMO_SBM.parquet")
>>> df.columns
['codigo_submercado', 'estagio', 'data_inicio', 'data_fim', 'cenario', 'patamar', 'duracao_patamar', 'valor', 'limite_inferior', 'limite_superior']

Todo código downstream que referencia colunas pelo nome deve ser atualizado. Exemplos comuns de mapeamento:

Exemplos de Renomeação de Colunas

Nome v1.x

Nome v2.x

Tipo

Estagio

estagio

i64

Data

data_inicio

datetime[ns, UTC]

Cenario

cenario

i64 ou str

Valor

valor

f64

Submercado

codigo_submercado

i64

Usina

codigo_usina

i64

REE

codigo_ree

i64

Indexação de Entidades

Na v1.x, as entidades do sistema (usinas, submercados, REEs, etc.) eram identificadas pelo nome textual nos DataFrames de síntese. Na v2.0.0, passaram a ser indexadas pelo código numérico da entidade. O mapeamento entre código e nome está disponível nos arquivos de síntese do sistema.

v1.x (antes) — entidades identificadas pelo nome:

>>> df = pd.read_parquet("sintese/EARMF_REE.parquet")
>>> df[["REE", "Estagio", "Valor"]].head(3)
   REE  Estagio      Valor
0  SUDESTE        1  30647.0
1  SUL            1  12345.0
2  NORDESTE       1   8901.0

v2.x (depois) — entidades identificadas pelo código numérico:

>>> df = pl.read_parquet("sintese/EARMF_REE.parquet")
>>> df[["codigo_ree", "codigo_submercado", "estagio", "valor"]].head(3)
shape: (3, 4)
┌────────────┬───────────────────┬─────────┬─────────┐
│ codigo_ree ┆ codigo_submercado ┆ estagio ┆ valor   │
│ ---        ┆ ---               ┆ ---     ┆ ---     │
│ i64        ┆ i64               ┆ i64     ┆ f64     │
╞════════════╪═══════════════════╪═════════╪═════════╡
│ 1          ┆ 1                 ┆ 1       ┆ 30647.0 │
│ 2          ┆ 1                 ┆ 1       ┆ 12345.0 │
│ 3          ┆ 3                 ┆ 1       ┆  8901.0 │
└────────────┴───────────────────┴─────────┴─────────┘

Para obter o mapeamento entre código e nome, consulte o arquivo REE.parquet da síntese do sistema:

>>> ree_df = pl.read_parquet("sintese/REE.parquet")
>>> ree_df[["codigo_ree", "nome_ree"]]

De forma análoga, sínteses por UHE passaram a incluir colunas adicionais com os códigos dos conjuntos que englobam a entidade, como codigo_ree e codigo_submercado, permitindo agrupamentos arbitrários.

Formato dos Arquivos Parquet

Aviso

Arquivos gerados pela v1.x não são compatíveis com a leitura padrão esperada pela v2.x sem decompressão explícita. Regenere as sínteses após a atualização.

Na v1.x, os arquivos Parquet eram comprimidos com gzip e tinham a extensão .parquet.gz. Na v2.0.0, a compressão padrão passou a ser snappy (padrão do Apache Arrow), e a extensão dos arquivos é simplesmente .parquet.

v1.x (antes):

$ ls sintese/
CMO_SBM.parquet.gz
EARMF_REE.parquet.gz
GHID_SIN.parquet.gz
...
>>> df = pd.read_parquet("sintese/CMO_SBM.parquet.gz")

v2.x (depois):

$ ls sintese/
CMO_SBM.parquet
EARMF_REE.parquet
GHID_SIN.parquet
...
>>> df = pl.read_parquet("sintese/CMO_SBM.parquet")

Além disso, colunas do tipo datetime passaram a garantir que o fuso horário seja UTC, aumentando a compatibilidade com outras implementações do Arrow.

Atualizar caminhos hardcoded de .parquet.gz para .parquet em qualquer script de leitura downstream.

Reestruturação dos Patamares

Na v1.x, a síntese da operação era dividida em duas variantes por agregação temporal: uma com sufixo EST (valor médio do estágio) e outra com sufixo PAT (por patamar). Na v2.0.0, essa distinção foi eliminada: todas as sínteses incluem sempre as colunas patamar e duracao_patamar.

A convenção adotada é:

  • patamar = 0 representa o valor médio do estágio (equivalente ao sufixo EST da v1.x)

  • patamar >= 1 representa os patamares individuais (equivalente ao sufixo PAT da v1.x)

  • duracao_patamar contém a duração em horas do patamar no estágio

v1.x (antes) — sínteses separadas por agregação temporal:

$ ls sintese/
GHID_REE_EST.parquet.gz   # valor médio do estágio
GHID_REE_PAT.parquet.gz   # por patamar

>>> df_est = pd.read_parquet("sintese/GHID_REE_EST.parquet.gz")
>>> df_est.columns.tolist()
['REE', 'Estagio', 'Data', 'Cenario', 'Valor']

v2.x (depois) — arquivo único com coluna patamar:

$ ls sintese/
GHID_REE.parquet   # contém patamar = 0 (médio) e patamar >= 1

>>> df = pl.read_parquet("sintese/GHID_REE.parquet")
>>> df.columns
['codigo_ree', 'codigo_submercado', 'estagio', 'data_inicio', 'data_fim',
 'cenario', 'patamar', 'duracao_patamar', 'valor', 'limite_inferior', 'limite_superior']

Para obter apenas o valor médio do estágio (equivalente ao _EST da v1.x):

>>> df_medio = df.filter(pl.col("patamar") == 0)

Para obter apenas os valores por patamar (equivalente ao _PAT da v1.x):

>>> df_pat = df.filter(pl.col("patamar") > 0)

Arquivos de Estatísticas

Na v2.0.0, as sínteses da operação e de cenários passaram a gerar arquivos adicionais com estatísticas pré-calculadas. Esses arquivos têm o prefixo ESTATISTICAS_ e são gerados automaticamente junto com os dados brutos.

v1.x (antes) — sem arquivos de estatísticas separados:

$ ls sintese/
EARMF_REE.parquet.gz
GHID_SBM.parquet.gz
...
# Estatísticas precisavam ser calculadas pelo usuário

v2.x (depois) — arquivos de estatísticas gerados automaticamente:

$ ls sintese/
EARMF_REE.parquet
ESTATISTICAS_OPERACAO_REE.parquet
ESTATISTICAS_OPERACAO_SBM.parquet
ESTATISTICAS_OPERACAO_SIN.parquet
ESTATISTICAS_OPERACAO_UHE.parquet
ESTATISTICAS_CENARIOS_REE_BKW.parquet
ESTATISTICAS_CENARIOS_REE_SF.parquet
...

Nos arquivos de estatísticas, a coluna cenario possui tipo str e assume os valores mean, std e percentis de 5 em 5 (min, p5, …, p45, median, p55, …, p95, max).

Consulte Saídas para detalhes sobre o formato completo dos arquivos de estatísticas.

Arquivos de Metadados

Na v2.0.0, cada categoria de síntese passou a gerar um arquivo de metadados com o prefixo METADADOS_. Esses arquivos descrevem as sínteses realizadas, incluindo informações como nome da variável, unidade, se é calculada e se é limitada.

v1.x (antes) — sem arquivos de metadados:

$ ls sintese/
CMO_SBM.parquet.gz
EARMF_REE.parquet.gz
...
# Não havia arquivos de metadados

v2.x (depois) — arquivo de metadados por categoria de síntese:

$ ls sintese/
CMO_SBM.parquet
EARMF_REE.parquet
...
METADADOS_OPERACAO.parquet
METADADOS_CENARIOS.parquet
METADADOS_SISTEMA.parquet
METADADOS_EXECUCAO.parquet
METADADOS_POLITICA.parquet

Para acessar os metadados de uma síntese:

>>> meta_df = pl.read_parquet("sintese/METADADOS_OPERACAO.parquet")
>>> meta_df[["chave", "nome_curto_variavel", "unidade", "calculado", "limitado"]]

Consulte Saídas para exemplos completos do conteúdo dos arquivos de metadados.

Sínteses de Violação Removidas

Na v1.x, variáveis que possuíam limites operativos geravam sínteses adicionais específicas para as violações (ex.: VVMINOP_UHE, VGHMIN_UHE). Na v2.0.0, essas sínteses específicas foram removidas e substituídas pelas colunas limite_inferior e limite_superior nos próprios dados brutos de cada variável.

v1.x (antes) — sínteses de violação como arquivos separados:

$ ls sintese/
VTUR_UHE.parquet.gz       # dados brutos
VVTUR_UHE.parquet.gz      # violação do limite de turbinamento
VARMI_REE.parquet.gz      # dados brutos
VVMINOP_REE.parquet.gz    # violação do volume mínimo operativo
...

v2.x (depois) — limites integrados como colunas nos dados brutos:

$ ls sintese/
VTUR_UHE.parquet    # contém colunas limite_inferior e limite_superior
VARMI_REE.parquet   # contém colunas limite_inferior e limite_superior
...
# Não há mais arquivos VVTUR_UHE, VVMINOP_REE, etc.

Para calcular violações com base nos dados da v2.x:

>>> df = pl.read_parquet("sintese/VTUR_UHE.parquet")
>>> violacoes = df.filter(
...     (pl.col("valor") < pl.col("limite_inferior")) |
...     (pl.col("valor") > pl.col("limite_superior"))
... )

Scripts de Migração Automática

Aviso

Não existem scripts de migração automática disponíveis. Toda adaptação do código downstream que consome as saídas do sintetizador deve ser realizada manualmente.

As mudanças na v2.0.0 afetam nomes de colunas, nomes de arquivos, tipos de dados e a estrutura de entidades. Recomenda-se a seguinte abordagem para a migração:

  1. Regenerar todas as sínteses com a versão v2.x instalada, pois os arquivos produzidos pela v1.x não são compatíveis com os novos nomes e extensões.

  2. Atualizar referências a colunas em todo o código downstream, substituindo os nomes v1.x pelos equivalentes em snake_case da v2.x.

  3. Substituir joins por nome de entidade por joins pelo código numérico, usando os arquivos de sistema (UHE.parquet, REE.parquet, SBM.parquet) para obter o mapeamento código-nome quando necessário.

  4. Atualizar extensões de arquivo de .parquet.gz para .parquet em todos os scripts de leitura.

  5. Revisar filtros por patamar: substituir leitura de arquivos _EST e _PAT pelo filtro patamar == 0 e patamar > 0 respectivamente.

  6. Remover leitura de sínteses de violação (arquivos VV*.parquet.gz), substituindo pelo cálculo a partir das colunas limite_inferior e limite_superior dos dados brutos.