Como usar
Um ponto é um tempo em nanossegundos, um valor e um peso. O valor é um
inteiro com um número fixo de casas decimais, então 101.25
continua 101.25 dos seus dados até o quadro.
Os guias levam uma tarefa do começo ao fim: escolher
entre um arquivo, tiles e um feed ao vivo, colocar seus dados, escolher a pirâmide,
servir, e desenhar no navegador, no .NET, a partir do C ou como imagem.
Seus dados: um CSV, sem código
nonius-server csv prices.csv prices.nsb
Vem com o cargo install nonius-server. Ele descobre as casas decimais,
lê tempos em ISO 8601 e o ponto e vírgula e a vírgula decimal de uma planilha, e para na
primeira linha que não consegue ler, dizendo qual. Depois, nonius-server
prices.nsb serve o arquivo.
De um programa, o mesmo arquivo sai de cada pacote, byte a byte: o
write_series do Rust, o Nsb.Encode do .NET, o
nonius_nsb_write do C e o encodeNsb no JavaScript, no
navegador ou no Node.
Rust: de um arquivo de série a uma imagem, sem GPU
cargo add nonius-format nonius-core
cargo add nonius-render --no-default-features
Leia o arquivo no lugar, guarde-o como uma pirâmide de resumos e desenhe
qualquer visualização dele; aqui, a série inteira:
use nonius_core::{Loaded, Pyramid, Series, Width, Zone};
use nonius_format::{AlignedBytes, Container};
use nonius_render::{Still, Theme, still_png};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Read once into memory aligned for the columns, then read in place.
let bytes = AlignedBytes::from_slice(&std::fs::read("day.nsb")?);
let container = Container::parse_checked(bytes.as_slice())?;
let series = Series::from_container(&container)?;
// Summaries from one second up, nine levels (see nonius-core's
// "Choosing the pyramid").
let mut pyramid = Pyramid::new(Width::new(1_000_000_000)?, 9)?;
pyramid.extend_sorted(series.iter())?;
let loaded = Loaded::new(&pyramid, (series.t(), series.v(), series.w()));
let (Some(&first), Some(&last)) = (series.t().first(), series.t().last()) else {
return Err("the file holds no points".into());
};
// The image's size is in device pixels; `ratio` scales labels and lines.
let png = still_png(&loaded, &Still {
start: first,
end: last + 1,
width: 2400,
height: 800,
theme: Theme::light(),
ratio: 2.0,
scale: series.scale(),
gap: None,
zone: Zone::UTC,
title: None,
unit: None,
})?;
std::fs::write("day.png", png)?;
Ok(())
}
Uma imagem diz onde está o gráfico e o que ele abrange, então um clique nela escolhe o
ponto exato e uma marca desenhada por cima cai onde a linha passa: o /png do
servidor responde Nonius-Plot e Nonius-Range, e o
still_placement, o nonius_still_placement do C e o
Series.StillPlacement do .NET dão os mesmos números.
O navegador: um gráfico que se arrasta e se amplia
npm install nonius
const chart = await createChart(canvas);
// Your points: times in nanoseconds since 1970 as BigInts, values as
// integers with a fixed number of decimal places (2 here: 10_000 is
// 100.00), and a weight each.
const { t, v, w } = randomWalk();
chart.setScale(2);
chart.push(t, v, w);
// Open on everything, the value axis fitted to it.
const [start, end] = [t[0], t[t.length - 1] + 1n];
const [lo, hi] = chart.autoscale(start, end, 0, 8);
chart.setView(start, end, lo, hi);
WebGPU quando o navegador tem, WebGL2 quando não tem, e um canvas 2D quando
nenhum dos dois oferece um dispositivo. O pacote também acompanha os tiles de
um servidor e recebe um feed ao vivo num worker; React e Vue o usam como
qualquer outro módulo.
Um sensor que envia dados em rajadas aparece com uma reta de uma rajada à
seguinte, a menos que você diga quanto tempo de pausa é uma lacuna:
chart.setSeriesGap(id, ns) quebra a linha onde um ponto chega mais de
ns nanossegundos depois do anterior, nos mesmos lugares em qualquer zoom.
O tempo sai em UTC até você indicar um fuso:
setTimeZone(chart, "America/Sao_Paulo") mostra o eixo, a mira e o
tooltip na hora local, dos dois lados de cada troca de horário de verão, com os
dados de fuso do próprio navegador. As imagens do servidor aceitam tz=, e o
gráfico do .NET, um TimeZoneInfo.
O título e a unidade ficam no próprio gráfico, não na página em volta:
createChart(canvas, { title: "Temperatura média", unit: "°C" }) desenha
uma linha de cabeçalho acima da área do gráfico, o título à esquerda e a unidade
sobre os valores, então um PNG enviado por e-mail ou um gráfico de desktop em .NET
diz o que mostra. Os rótulos desenham Latin-1 — todos os acentos do português, do
espanhol, do francês e do alemão — e alguns sinais, como € e “ ”. As imagens do
servidor aceitam title= e unit=, e o gráfico do .NET,
Title e Unit.
.NET: o mesmo núcleo, em C#
dotnet add package Nonius
using var series = Series.FromNsb(File.ReadAllBytes(nsb));
if (!series.TryGetRange(out var first, out var last))
{
throw new InvalidDataException($"{nsb} holds no points");
}
// Light, for a box of 1200 × 400 CSS pixels at a pixel ratio of 2:
// the size is in device pixels, the ratio in thousandths.
byte[] image = series.StillPng(new Still(first, last + 1, 2400, 800, Theme.Light, RatioPermille: 2000));
File.WriteAllBytes(png, image);
Nonius.Avalonia é um controle de gráfico para desktop, e
Nonius.Blazor um componente que traz o pacote do navegador.