Incerteza e unidades
Escopo
Use esta skill sempre que um cálculo envolver unidades físicas ou um número relatado precisar de incerteza. Concretamente:
- converter entre unidades, incluindo conversões que precisam de um contexto físico (comprimento de onda para energia de fóton, massa para quantidade de substância, energia para temperatura);
- propagar incerteza através de um modelo de medição, com ou sem entradas correlacionadas;
- construir um orçamento de incerteza GUM a partir de certificados de calibração, especificações e dados de repetitividade;
- escolher um fator de abrangência e decidir se
k = 2é defensável; - arredondar e escrever um resultado para que o leitor saiba o que o
±significa; - extrair incertezas de parâmetros de um ajuste de curva sem descartar correlações;
- revisar código de análise existente para detectar defeitos silenciosos de unidades e incerteza;
- verificar se uma resposta dimensionalmente consistente também é fisicamente possível — a ordem de grandeza, o grupo adimensional e o regime que ele implica.
Esta skill cobre a metrologia e as duas bibliotecas que a implementam. Não cobre inferência estatística, seleção de modelos ou desenho de estudos — veja statistical-analysis, statistical-power e experimental-design.
Versão atual e instalação
Verificado em 2026-07-26:
- pint 0.25.3, lançado em 2026-03-19; requer Python 3.11+.
- uncertainties 3.2.3, lançado em 2025-04-21; requer Python 3.8+.
- NumPy 2.5.1 e SciPy 1.18.0; ambos requerem Python 3.12+.
scipy.constantsno SciPy 1.18.0 fornece CODATA 2022. SciPy 1.11 e anteriores forneciam CODATA 2018, e vários valores recomendados diferem entre eles.
uv venv --python 3.13
source .venv/bin/activate
uv pip install "pint==0.25.3" "uncertainties==3.2.3" "numpy==2.5.1" "scipy==1.18.0"
pint-pandas e pint-xarray adicionam colunas e arrays com ciência de unidades e são instalações separadas.
Fluxo de trabalho inegociável
- Anexe unidades na entrada e remova-as apenas na saída. Converta nos limites das funções com
ureg.wrapsoum_as("unidade"), nunca no meio do cálculo. - Escreva o modelo de medição explicitamente antes de calcular qualquer coisa, incluindo correções cujo valor estimado é zero. Uma correção omitida do modelo deixa sua incerteza fora do orçamento.
- Dê a cada entrada quatro coisas: uma estimativa, uma incerteza padrão, a distribuição de onde veio a incerteza e seus graus de liberdade.
- Converta declarações Tipo B com o divisor correto. A incerteza expandida de um certificado divide pelo seu
kdeclarado; limites retangulares dividem porsqrt(3). - Identifique correlações antes de combinar. Entradas calibradas contra o mesmo padrão, medidas no mesmo instrumento ou obtidas do mesmo ajuste estão correlacionadas.
- Calcule coeficientes de sensibilidade e leia o orçamento de
c_i * u(x_i)em vez das incertezas brutas. - Verifique a linearização. Execute Monte Carlo junto com o framework GUM e aplique o teste de comparação da cláusula 8 do JCGM 101. Relate o resultado Monte Carlo quando ele falhar.
- Escolha
ka partir dos graus de liberdade efetivos, não por hábito. - Arredonde a incerteza primeiro, depois o valor para a mesma casa decimal.
- Declare o que o
±é — padrão ou expandido, comk, a probabilidade de abrangência e o método. - Verifique a magnitude antes de relatar. Um resultado dimensionalmente consistente ainda pode ser impossível. Compare-o com uma escala conhecida ou um grupo adimensional e confirme que cada suposição em que você confiou ainda é válida naquele regime.
As falhas que esta skill existe para prevenir
Cada um dos exemplos a seguir é executado sem erro e produz um número plausível.
Uma unidade removida em uma escala desconhecida
length = (12.7 * ureg.mm).magnitude # 12.7 -- de quê?
length = (12.7 * ureg.mm).m_as("m") # 0.0127 metros, declarado
.magnitude retorna o que a quantidade estiver carregando. Nomeie a unidade no ponto de extração, sempre.
Aritmética de temperatura offset
Q(20, "degC") + Q(5, "degC") # OffsetUnitCalculusError -- corretamente recusado
Q(20, "degC") + Q(5, "delta_degC") # 25 degree_Celsius
Q(25, "degC") - Q(20, "degC") # 5 delta_degree_Celsius
Celsius e Fahrenheit são escalas intervalares. Uma incerteza sobre uma temperatura é sempre uma diferença e pertence a uma unidade delta_: converter 20 ± 0.5 degC para Fahrenheit dá 68 degF ± 0.9 delta_degF, duas conversões diferentes em uma linha.
Unidades logarítmicas que somam multiplicando
Q(10, "dBm") + Q(10, "dBm") # 0.0001 kilogram**2 * meter**4 / second**6
Isso é 10 mW × 10 mW, não 20 mW e nem 13 dBm. Nada é levantado. Converta para uma unidade linear antes de qualquer aritmética.
Uma correlação destruída por uma ida e volta
x = ufloat(1.0, 0.1)
x - x # 0.0+/-0
x - ufloat(x.nominal_value, x.std_dev) # 0.00+/-0.14
Recriar uma variável a partir de seu valor nominal e desvio padrão cria uma variável independente. O mesmo vale para qualquer serialização que passa por um par de floats. Use correlated_values(values, covariance_matrix) para recriar um conjunto correlacionado.
Uma matriz de covariância silenciosamente redimensionada
popt, pcov = curve_fit(f, x, y, sigma=sigma) # padrão
popt, pcov = curve_fit(f, x, y, sigma=sigma, absolute_sigma=True)
O comportamento padrão redimensiona pcov pelo qui-quadrado reduzido, então as incertezas dos parâmetros absorvem a qualidade do ajuste e correspondem ao que você obteria passando nenhum sigma. Em um ajuste de linha reta sintético, os dois dão [0.0364, 0.2154] e [0.0477, 0.2820] — uma diferença de 31%. Use absolute_sigma=True sempre que sigma contiver incertezas padrão reais.
Uma linearização que nunca foi verificada
Para y = x² com x = 1.0 ± 0.5, o framework GUM dá y = 1.0, u_c = 1.0 e um intervalo de 95% de [-0.96, 2.96] — principalmente negativo, para uma quantidade ao quadrado. Monte Carlo dá uma média de 1.25, u_c = 1.06 e um intervalo mais curto de 95% de [0, 3.32]. Nada em uma biblioteca de propagação linear lhe dirá que isso aconteceu.
CLIs locais incluídas
Todos os ajudantes funcionam offline, rejeitam URLs e links simbólicos, limitam suas entradas, escrevem a saída atomicamente com permissões privadas e se recusam a sobrescrever sem --force.
python skills/uncertainty-and-units/scripts/propagate_uncertainty.py --help
python skills/uncertainty-and-units/scripts/uncertainty_budget.py --help
python skills/uncertainty-and-units/scripts/format_result.py --help
python skills/uncertainty-and-units/scripts/convert_units.py --help
python skills/uncertainty-and-units/scripts/audit_units.py --help
python skills/uncertainty-and-units/scripts/check_plausibility.py --help
propagate_uncertainty.py
Executa ambos os métodos de propagação no mesmo modelo e aplica o teste de validação da cláusula 8 do JCGM 101.
python skills/uncertainty-and-units/scripts/propagate_uncertainty.py \
--expression "m / (pi * (d / 2) ** 2 * h)" \
--variable "m=250.0,0.05" \
--variable "d=20.0,0.02,rectangular" \
--variable "h=40.0,0.05,rectangular" \
--measurand density --unit "g/cm3" --format markdown
Cada --variable é nome=valor,incerteza_padrão[,distribuição[,gdl]], onde a distribuição é normal, rectangular, triangular, arcsine ou exact e controla apenas a amostragem Monte Carlo. Correlações são inseridas como --correlation "a,b=0.9". Um arquivo --spec JSON contém o mesmo modelo para qualquer coisa de longa duração.
A expressão é analisada em uma árvore sintática abstrata e reduzida por uma caminhada explícita sobre + - * / ** e uma lista fixa de funções. Nunca é compilada ou executada.
O relatório fornece a estimativa, u_c, coeficientes de sensibilidade, o orçamento em porcentagem, graus de liberdade efetivos, k, U, ambos os intervalos de cobertura Monte Carlo e o veredito sobre se o resultado linearizado pode ser relatado.
uncertainty_budget.py
Combina componentes declarados da forma como certificados e folhas de dados os declaram.
python skills/uncertainty-and-units/scripts/uncertainty_budget.py --template > budget.json
python skills/uncertainty-and-units/scripts/uncertainty_budget.py --spec budget.json --format markdown
Cada componente nomeia uma distribution que fixa seu divisor — expanded divide por seu coverage_factor, rectangular por sqrt(3), triangular por sqrt(6), arcsine por sqrt(2), normal por 1 — com sensitivity, dof e relative: true opcionais. A ferramenta calcula u_c, os graus de liberdade efetivos de Welch-Satterthwaite, k a partir da distribuição t e U, e avisa quando um componente Tipo A não tem graus de liberdade, quando nu_eff é pequeno o suficiente para que k = 2 esteja errado, quando um componente domina e quando um componente Tipo B declarado normal é provavelmente uma incerteza expandida não dividida.
format_result.py
python skills/uncertainty-and-units/scripts/format_result.py \
--value 12.34567 --uncertainty 0.02345 --unit mm \
--coverage-factor 2.26 --coverage-probability 0.95
Retorna 12.346 ± 0.023 mm, 12.346(23) mm, as formas científica e LaTeX, e a frase que deve acompanhar o número. Avisa quando um dígito significativo é solicitado para uma incerteza começando em 1 ou 2 e quando a incerteza excede a estimativa.
convert_units.py
python skills/uncertainty-and-units/scripts/convert_units.py \
--value 532 --unit nm --to eV --context spectroscopy --uncertainty 0.5
python skills/uncertainty-and-units/scripts/convert_units.py \
--value 1.0 --unit g --to mol --context chemistry --context-parameter "mw=180.156 g/mol"
Carrega a incerteza através da derivada local da conversão, o que importa porque conversões contextuais são recíprocas em vez de proporcionais. Nomeia o contexto na mensagem de erro quando uma conversão precisa de um e sinaliza unidades offset e logarítmicas. --list-contexts mostra o que o registro define.
audit_units.py
Revisão estática de código de análise existente. Analisa, nunca importa ou executa.
python skills/uncertainty-and-units/scripts/audit_units.py \
--input analysis.py --format markdown --fail-on medium
| Regra | Gravidade | Detecta |
|---|---|---|
UNIT001 | medium | um segundo UnitRegistry em um módulo — ValueError entre registros |
UNIT002 | medium | unidades de temperatura offset sem nenhuma unidade delta_ |
UNIT003 | high | .magnitude sem um .to(...) ou .m_as(...) precedente |
UNIT004 | medium | unidades logarítmicas, cujo + multiplica |
UNC001 | high | curve_fit sem absolute_sigma |
UNC002 | medium | np.std / np.var sem ddof |
UNC003 | medium | funções math ou numpy em um módulo que usa uncertainties |
UNC004 | high | um ufloat reconstruído a partir de .nominal_value e .std_dev |
CONST001 | low | um literal dentro de 0.1% de uma constante CODATA |
O status de saída é 1 quando um achado atende --fail-on (padrão high), o que o torna utilizável como uma verificação de pré-commit ou CI.
As regras são heurísticas, então um falso positivo é suprimido com um comentário diretivo — no final da linha para cobrir sua própria linha, ou sozinho em uma linha para cobrir a próxima:
value = quantity.magnitude # audit-units: ignore UNIT003 -- já convertido a montante
# audit-units: ignore UNC003 -- o argumento aqui é um array simples de floats
scaled = np.log10(counts)
# audit-units: ignore-file CONST001 cobre um módulo inteiro, e nomear nenhuma regra suprime todas. As supressões são contadas no relatório em vez de ocultadas, então um arquivo que silencia tudo ainda informa isso.
check_plausibility.py
Consistência dimensional não é possibilidade física. Uma célula de 2 m de diâmetro e um número de Reynolds de 4e7 em um capilar ambos passam em todas as verificações de unidade. Esta ferramenta testa um conjunto de quantidades contra grupos adimensionais, escalas características e bandas de magnitude selecionadas, e verifica a dimensionalidade de cada fórmula antes de relatar um número.
python skills/uncertainty-and-units/scripts/check_plausibility.py \
--quantity "density=1060 kg/m**3" --quantity "velocity=0.5 mm/s" \
--quantity "length=8 um" --quantity "viscosity=3.5 mPa*s" \
--group reynolds --format markdown
# Re = 0.001211 -- laminar (tubo circular, comprimento = diâmetro)
python skills/uncertainty-and-units/scripts/check_plausibility.py \
--quantity "diameter=2 m" --band "eukaryotic_cell_diameter=diameter"
# implausível: 4.3 décadas fora da faixa de 5-100 um
--group avalia um dos 14 grupos adimensionais e nomeia o regime em que coloca o sistema; --scale calcula uma escala característica como tempo de difusão, comprimento de Debye ou velocidade de sedimentação de Stokes; --band compara uma quantidade fornecida com uma faixa observada. --list imprime todo o catálogo com as entradas que cada fórmula precisa.
Constantes físicas (k_B, N_A, R_gas, g_earth e o restante) estão disponíveis para cada fórmula sem serem fornecidas e são lidas de scipy.constants em tempo de execução em vez de escritas como literais, para que acompanhem a versão CODATA que o SciPy distribui.
A verificação de dimensionalidade é o ponto. Passar uma viscosidade cinemática onde a fórmula precisa de uma dinâmica — ambas chamadas "viscosidade", ambas tabeladas para água, diferindo por um fator de ρ — é recusado antes que qualquer número seja computado:
erro: viscosidade deve ter dimensionalidade [massa] / ([comprimento] * [tempo]),
mas m²/s é [comprimento] ** 2 / [tempo]
O status de saída é 1 quando o veredito atinge --fail-on (padrão implausible; um valor dentro de uma década de uma banda é questionable). Os limiares são convenções com bordas suaves e assumem a geometria para a qual sua correlação foi ajustada — veja references/plausibility-scales.md para o comprimento característico a usar em cada caso.
Escolhendo um método de propagação
| Situação | Método |
|---|---|
| Modelo linear ou quase linear, entradas aproximadamente normais, muitos gdl | Apenas framework GUM |
| Qualquer não linearidade em ±2u de uma entrada | execute ambos, aplique o teste da cláusula 8 |
| Incerteza relativa acima de ~20% em qualquer entrada | Monte Carlo obrigatório, com verificação da cláusula 8 como diagnóstico. |