Pesquisa¶
O kit de pesquisa / ciência de dados é a camada que um pesquisador acadêmico
usa para mostrar o resultado de um modelo ONNX /
ort-vision-sdk de ponta
a ponta: cartões de métrica num dashboard, gráficos simples (linha / barra),
caixas de detecção sobre uma imagem e o fluxo escolher imagem → mostrar
resultado. Tudo aqui abaixa para primitivas que já existem (composição) ou
para uma lista de comandos do Canvas (gráficos / overlays) — nenhum campo
novo de Style, nenhum resolver novo e nenhum comando de desenho novo é
introduzido. 🔬
O que você aprende aqui
- Como
MetricCard/StatCardcompõem oCard(H3) +Stat(H4) sem inventar primitiva. - Como a função pura
confidence_schememapeia confiança → status e alimenta tanto oConfidenceBadgequanto oDetectionOverlay. - Como
LineChart/BarChartemitem uma lista de comandos determinística doCanvasusando só o vocabulário de desenho existente. - Por que um
DetectionBoxéxyxynormalizado em[0, 1]e como ele vira caixas sobre umaImage. - Como o
ResultViewarranja o fluxo picker → resultado sem guardar estado.
Cartões de métrica¶
O bloco de topo de um dashboard: um número grande com um rótulo e uma tendência.
Nada aqui é uma primitiva nova — os cartões compõem o Card e o Stat, e o
selo de confiança compõe o Badge. A cor de status sai toda de uma única função
pura, confidence_scheme.
MetricCard¶
Uma métrica de dashboard dentro de um cartão temático: rótulo, valor e uma
tendência opcional tingida (success para cima, error para baixo). No caso
mínimo você passa só label e value:
from tempest_core import MetricCard
acuracia = MetricCard(label="Acurácia", value="92%", delta="+3%", delta_up=True)
Precisa de um mini-gráfico ao lado do número? O slot trailing aceita qualquer
widget — por exemplo um LineChart fazendo as vezes de sparkline:
from tempest_core import ChartSeries, LineChart, MetricCard
spark = LineChart(
series=[ChartSeries(points=[0.80, 0.86, 0.89, 0.92])],
width=96.0,
height=40.0,
)
acuracia = MetricCard(
label="Acurácia",
value="92%",
delta="+3%",
delta_up=True,
color_scheme="success",
trailing=spark,
)
Props¶
| Prop | Tipo | Padrão | O que faz |
|---|---|---|---|
label |
str |
"" |
A legenda da métrica (mostrada apagada/muted). |
value |
str |
"" |
O valor da métrica (grande e proeminente). |
delta |
str \| None |
None |
A linha de tendência (ex.: "+12%"); None esconde. |
delta_up |
bool |
True |
Se o delta é positivo (tingido de success) ou negativo (error). |
color_scheme |
str |
"neutral" |
A família de papéis M3 com que a superfície do cartão tinge. |
variant |
CardVariant |
ELEVATED |
O tratamento da superfície (elevated / filled / outlined). |
trailing |
Widget \| None |
None |
Um widget opcional à direita do bloco de stat (sparkline, ícone…). |
theme |
Theme |
Theme() |
O tema cujos tokens resolvem a superfície e o stat. Não entra na IR. |
media |
MediaQueryData \| None |
None |
Snapshot de viewport (aceito por paridade; não usado aqui). |
É Card + Stat, não uma primitiva nova
O render do MetricCard monta um Stat (o bloco rótulo/valor/delta da H4) e
o embrulha num Card (a superfície da H3). Quando trailing está setado, o
stat e o widget extra entram num Row centralizado; senão o stat é o corpo
direto. Nada além dessas duas primitivas compostas — o cartão herda de graça
todo o comportamento de superfície e de tokens delas.
StatCard¶
Um preset compacto do MetricCard: exatamente o mesmo componente, só que com a
superfície mais densa por padrão (filled em vez de elevated). Serve para uma
grade apertada de números:
Props¶
O StatCard herda todos os props do MetricCard — a única diferença é o
padrão de variant.
| Prop | Tipo | Padrão | O que faz |
|---|---|---|---|
variant |
CardVariant |
FILLED |
A superfície densa do preset (sobreponha para retunar). |
| (demais) | — | (iguais ao MetricCard) |
label, value, delta, delta_up, color_scheme, trailing, theme, media. |
Quando cada um
Use MetricCard (elevado) para os KPIs de destaque de uma tela; use StatCard
(preenchido, mais apertado) para uma fileira/grade de números secundários que
não devem competir por atenção. Como StatCard é um MetricCard, todo
prop continua valendo — inclusive dá para sobrepor variant de volta para
ELEVATED se quiser.
ConfidenceBadge¶
Uma pílula de status que mostra a confiança de um modelo, colorida por limiar.
Compõe o Badge (H4), escolhe o color_scheme via confidence_scheme e rotula
como uma porcentagem arredondada. Um label opcional vira prefixo:
from tempest_core import ConfidenceBadge
# Pílula verde "gato 92%" (>= 80% => success).
confianca = ConfidenceBadge(confidence=0.92, label="gato")
# Sem rótulo, só a porcentagem — e com limiares próprios.
bruta = ConfidenceBadge(confidence=0.63, high=0.9, mid=0.6) # "63%", amber
Props¶
| Prop | Tipo | Padrão | O que faz |
|---|---|---|---|
confidence |
float |
(obrigatório) | A confiança do modelo em [0, 1]. |
label |
str |
"" |
Um prefixo opcional (ex.: a classe prevista) antes da porcentagem. |
high |
float |
0.8 |
O limiar de success passado ao confidence_scheme. |
mid |
float |
0.5 |
O limiar de warning passado ao confidence_scheme. |
theme |
Theme |
Theme() |
O tema cujos tokens resolvem a pílula. Não entra na IR. |
Variante SUBTLE por acessibilidade
O selo pinta com BadgeVariant.SUBTLE (o par tonal container, seguro para
WCAG-AA), não com SOLID. Um SOLID pintaria branco sobre o papel de
status saturado — success (~3.02) e warning (~4.0) falham o contraste
AA. A escolha espelha a decisão da H4 e mantém o selo legível em qualquer
família de status.
confidence_scheme¶
A função pura por trás de toda cor de confiança do kit. É o clássico semáforo:
>= high é verde ("success"), >= mid é âmbar ("warning"), abaixo é vermelho
("error"). Como é pura e determinística, todo componente conduzido por confiança
(selo, caixa de detecção) colore de forma consistente:
from tempest_core import confidence_scheme
confidence_scheme(0.92) # "success"
confidence_scheme(0.63) # "warning"
confidence_scheme(0.31) # "error"
confidence_scheme(0.63, high=0.9, mid=0.6) # "warning" (limiares próprios)
Assinatura¶
confidence_scheme(conf: float, *, high: float = 0.8, mid: float = 0.5) -> str
| Parâmetro | Tipo | Padrão | O que faz |
|---|---|---|---|
conf |
float |
(obrigatório) | O score de confiança, tipicamente em [0, 1]. |
high |
float |
0.8 |
Limiar inclusivo a partir do qual o score lê como alto ("success"). |
mid |
float |
0.5 |
Limiar inclusivo a partir do qual lê como médio ("warning"); abaixo, baixo ("error"). |
Limiares inclusivos, comparação em cascata
A comparação é conf >= high primeiro, depois conf >= mid, senão error —
logo os limiares são inclusivos (exatamente 0.8 com o padrão já é
success). Passe seus próprios high / mid para recalibrar sem trocar de
função: o ConfidenceBadge e o DetectionOverlay repassam esses dois nomes
direto para cá.
Gráficos sobre o Canvas¶
Os gráficos não são widgets novos: cada um abaixa para um Canvas carregando
uma lista de comandos de desenho. A lista é determinística para uma entrada
fixa — a suíte de conformância fixa a sequência exata — e usa só o vocabulário de
desenho que já existe. Os dados chegam num ChartSeries congelado, então um mesmo
gráfico plota várias séries nomeadas e coloridas.
ChartSeries¶
Uma única série de dados nomeada e (opcionalmente) colorida. Um gráfico recebe uma
lista desses em vez de um list[float] cru, para plotar várias séries de uma
vez, cada uma com seu rótulo e — se quiser — seu próprio color_scheme. É um
modelo congelado (frozen):
from tempest_core import ChartSeries
loss = ChartSeries(points=[0.90, 0.42, 0.31, 0.18], label="loss", color_scheme="error")
acc = ChartSeries(points=[0.55, 0.71, 0.84, 0.92], label="acc", color_scheme="success")
Props¶
| Prop | Tipo | Padrão | O que faz |
|---|---|---|---|
points |
list[float] |
[] |
Os valores-y da série, na ordem de plotagem (um por posição x). |
label |
str |
"" |
Um rótulo opcional (ex.: para legenda; carregado, não desenhado pelos gráficos mínimos). |
color_scheme |
str \| None |
None |
A família de papéis M3 da série; None cai na paleta rotativa do gráfico. |
Paleta rotativa quando color_scheme é None
Quando uma série não nomeia sua cor, o gráfico escolhe da paleta rotativa
(primary → secondary → tertiary → error → success → warning →
info) pelo índice da série. Assim duas séries sem cor nunca saem iguais, e
você só precisa setar color_scheme quando a cor importa semanticamente.
LineChart¶
Um gráfico de linhas multi-série desenhado sobre um Canvas. Cada ChartSeries
vira uma polilinha conectada sobre um plot emoldurado, com gridlines no eixo Y e
rótulos de tick alinhados à direita:
from tempest_core import ChartSeries, LineChart
curva = LineChart(
series=[
ChartSeries(
points=[0.90, 0.42, 0.31, 0.18], label="loss", color_scheme="error"
),
ChartSeries(
points=[0.55, 0.71, 0.84, 0.92], label="acc", color_scheme="success"
),
],
width=320.0,
height=200.0,
)
Props¶
| Prop | Tipo | Padrão | O que faz |
|---|---|---|---|
series |
list[ChartSeries] |
[] |
As séries a plotar (cada uma sua polilinha + cor). |
width |
float |
320.0 |
A largura do canvas, em pixels lógicos. |
height |
float |
200.0 |
A altura do canvas, em pixels lógicos. |
color_scheme |
str |
"primary" |
A família M3 padrão de uma série sem cor própria. |
theme |
Theme |
Theme() |
O tema cujos tokens viram as cores concretas. Não entra na IR. |
Vocabulário de desenho — não existe DrawLine
Uma linha é MoveTo + uma sequência de LineTo + um único StrokeCmd; os
eixos e as gridlines saem do mesmo trio. Os rótulos do eixo Y são DrawText
(ancorado na baseline, sem campo de alinhamento) — para alinhá-los à direita
o engine desloca a âncora para a esquerda estimando a largura do texto. Nenhum
comando de desenho novo foi criado, e a lista final é determinística para
entrada fixa.
BarChart¶
Um gráfico de barras sobre um Canvas. Aceita ou uma lista de ChartSeries (a
primeira série vira as barras) ou, para o caso trivial de série única, uma
values: list[float] simples com labels opcionais:
from tempest_core import BarChart
# Caminho simples: uma lista de valores (+ rótulos).
barras = BarChart(values=[3.0, 5.0, 2.0], labels=["a", "b", "c"])
from tempest_core import BarChart, ChartSeries
# Caminho tipado: a primeira série vira as barras, com cor explícita.
barras = BarChart(
series=[ChartSeries(points=[3.0, 5.0, 2.0], color_scheme="tertiary")],
labels=["a", "b", "c"],
)
Props¶
| Prop | Tipo | Padrão | O que faz |
|---|---|---|---|
series |
list[ChartSeries] |
[] |
As séries (a primeira é plotada como barras). Opcional se values for dado. |
values |
list[float] |
[] |
Uma lista de valores de série única (usada quando series está vazio). |
labels |
list[str] |
[] |
Rótulos opcionais do eixo X para as barras. |
width |
float |
320.0 |
A largura do canvas, em pixels lógicos. |
height |
float |
200.0 |
A altura do canvas, em pixels lógicos. |
color_scheme |
str |
"primary" |
A família M3 padrão das barras (se a série não nomear a sua). |
theme |
Theme |
Theme() |
O tema cujos tokens viram as cores concretas. Não entra na IR. |
Barra é DrawRect + FillCmd; series vence values
Cada barra é um DrawRect seguido de um FillCmd sobre o mesmo plot
emoldurado dos eixos. Quando os dois series e values são passados, o
series ganha (usa-se o points e o color_scheme da primeira série);
values só entra quando series está vazio. A baseline sempre inclui o 0,
então as barras têm um chão com significado. A sequência de comandos é
determinística — a suíte de conformância a fixa.
Overlay de detecção¶
Um resultado de detecção de objetos é uma imagem com caixas por cima. O engine
não depende do ort-vision-sdk: as caixas chegam normalizadas em [0, 1], o
que as deixa independentes de resolução, e o adaptador de um resultado Detection
real para DetectionBox mora do lado do tempestroid, não aqui.
DetectionBox¶
Uma caixa de detecção xyxy normalizada em [0, 1] — as coordenadas são
frações da largura/altura do canvas (0 = esquerda/topo, 1 = direita/baixo),
multiplicadas pelo tamanho em pixels só na hora de desenhar. É um modelo
congelado (frozen):
from tempest_core import DetectionBox
gato = DetectionBox(x1=0.10, y1=0.20, x2=0.50, y2=0.60, name="gato", conf=0.93)
Props¶
| Prop | Tipo | Padrão | O que faz |
|---|---|---|---|
x1 |
float |
(obrigatório) | A borda esquerda como fração da largura ([0, 1]). |
y1 |
float |
(obrigatório) | A borda de topo como fração da altura ([0, 1]). |
x2 |
float |
(obrigatório) | A borda direita como fração da largura ([0, 1]). |
y2 |
float |
(obrigatório) | A borda de baixo como fração da altura ([0, 1]). |
name |
str |
"" |
Um rótulo de classe opcional desenhado ao lado da caixa. |
conf |
float |
1.0 |
A confiança em [0, 1] (dita a cor da caixa e a porcentagem do rótulo). |
Normalizado = resolução-independente
Como as coordenadas são frações, a mesma caixa desenha certo em qualquer
tamanho de canvas — troque o width/height do overlay e as caixas
acompanham. É a convenção xyxy normalizada comum, mas sem acoplar o engine a
nenhuma SDK de visão. Escreva um adaptador det.box.xyxy → DetectionBox no
seu app.
DetectionOverlay¶
Uma imagem com caixas de detecção por cima. Abaixa para um Stack de uma Image
base (fit=COVER) sob um Canvas de overlay; cada DetectionBox é multiplicada
pelo tamanho do canvas e desenhada como um retângulo traçado, colorido por
confidence_scheme, com uma legenda "{name} {conf:.0%}":
from tempest_core import DetectionBox, DetectionOverlay
overlay = DetectionOverlay(
image_src="foto.jpg",
boxes=[
DetectionBox(x1=0.10, y1=0.20, x2=0.50, y2=0.60, name="gato", conf=0.93),
DetectionBox(x1=0.55, y1=0.30, x2=0.90, y2=0.80, name="cão", conf=0.61),
],
width=320.0,
height=320.0,
)
Props¶
| Prop | Tipo | Padrão | O que faz |
|---|---|---|---|
image_src |
str |
(obrigatório) | A fonte da imagem (URL ou caminho de asset) a emoldurar. |
boxes |
list[DetectionBox] |
[] |
As caixas normalizadas a desenhar. |
width |
float |
320.0 |
A largura do canvas/imagem, em pixels lógicos. |
height |
float |
320.0 |
A altura do canvas/imagem, em pixels lógicos. |
high |
float |
0.8 |
O limiar de success passado ao confidence_scheme. |
mid |
float |
0.5 |
O limiar de warning passado ao confidence_scheme. |
theme |
Theme |
Theme() |
O tema cujos tokens dão a cor do rótulo. Não entra na IR. |
Stack(Image + Canvas) — cada caixa é traço + rótulo, sem comando novo
O overlay é um Stack da Image (COVER) sob um Canvas. Cada caixa vira um
DrawRect + StrokeCmd (na cor de confidence_scheme(box.conf, high=..., mid=...))
e, quando há legenda, um pequeno fundo (DrawRect + FillCmd) mais o texto
DrawText no par on_<scheme> para contraste. Cada caixa colore consistente
com o ConfidenceBadge porque as duas passam pela mesma função. Nenhum
comando de desenho novo é introduzido.
Fluxo selecionar → resultado¶
O último elo: escolher uma imagem, rodar a inferência e mostrar o resultado. O
componente não guarda estado — o app é dono da inferência e monta o widget de
resultado; o ResultView só arranja o picker e o resultado numa coluna.
ResultView¶
Empilha um ImagePicker sobre um slot result opcional — o widget que o app
constrói a partir da saída do modelo (um DetectionOverlay, um MetricCard, um
ConfidenceBadge ou um gráfico):
from tempest_core import DetectionBox, DetectionOverlay, ResultView
def ao_escolher(uri: str) -> None:
"""Roda a inferência e guarda o resultado no estado do app."""
... # o app roda o modelo e faz set_state com o widget montado
view = ResultView(
label="Envie uma foto",
on_pick=ao_escolher,
result=DetectionOverlay(
image_src="foto.jpg",
boxes=[DetectionBox(x1=0.1, y1=0.2, x2=0.5, y2=0.6, name="gato", conf=0.93)],
),
)
Props¶
| Prop | Tipo | Padrão | O que faz |
|---|---|---|---|
value |
str |
"" |
O URI da imagem escolhida (repassado ao picker; "" até escolher). |
label |
str |
"" |
Um título opcional acima do picker. |
on_pick |
Callable[[str], Any] |
(obrigatório) | Chamado com o URI da imagem escolhida na seleção. |
result |
Widget \| None |
None |
O widget de resultado abaixo do picker; None mostra só o picker. |
theme |
Theme |
Theme() |
O tema cujos tokens dão o espaçamento. Não entra na IR. |
O app é dono da inferência
O render monta um Column de um ImagePicker e, quando setado, o result.
O componente não roda modelo nenhum: você trata o on_pick, roda a inferência,
monta o widget de resultado (overlay, cartão, gráfico…) e o passa de volta em
result num rebuild. Isso mantém o ResultView sem estado e reusável para
qualquer tarefa de visão — classificação, detecção ou segmentação.
Recapitulando¶
- Tudo compõe ou desenha — nenhum componente de pesquisa inventa primitiva,
campo de
Style, resolver ou comando de desenho novo. - Cartões:
MetricCard=Card(H3) +Stat(H4);StatCardé o mesmo, presetfilledcompacto;ConfidenceBadge=Badge(H4)SUBTLE, colorido porconfidence_scheme. confidence_scheme(conf, *, high=0.8, mid=0.5)é a função pura e determinística por trás de toda cor de confiança:>= high→success,>= mid→warning, senãoerror.- Gráficos:
LineChart/BarChartabaixam para uma lista de comandos determinística doCanvas— linha =MoveTo+LineTo+StrokeCmd, barra =DrawRect+FillCmd, semDrawLine. Os dados vêm numChartSeriescongelado; noBarChart,seriesvencevalues. - Detecção:
DetectionBoxéxyxynormalizado em[0, 1]; oDetectionOverlayé umStack(Image COVER + Canvas)que colore cada caixa pela mesmaconfidence_scheme, sem depender doort-vision-sdk. ResultViewarranjaImagePicker+ slotresultsem estado — o app roda a inferência e monta o resultado.