Rust数据分析可视化插件库re_viewer_context的使用,实现高效数据查看与上下文管理
re_viewer_context
Rerun系列crate的一部分。
![Latest version] ![Documentation] ![MIT] ![Apache]
Rerun查看器不同模块的基本构建块。最突出的是包含一个上下文对象,查看器使用该对象与每个模块共享全局数据。
安装
在项目目录中运行以下Cargo命令:
cargo add re_viewer_context
或者在Cargo.toml中添加以下行:
re_viewer_context = "0.24.1"
使用示例
以下是一个使用re_viewer_context的基本示例:
use re_viewer_context::{ViewerContext, ViewerContextProvider};
// 定义一个自定义模块
struct MyModule;
impl ViewerContextProvider for MyModule {
fn on_register(&self, ctx: &mut ViewerContext) {
// 注册模块时初始化
println!("MyModule registered!");
}
fn on_update(&self, ctx: &mut ViewerContext) {
// 每次更新时执行
println!("MyModule updating with context: {:?}", ctx);
}
}
fn main() {
// 创建查看器上下文
let mut ctx = ViewerContext::new();
// 注册自定义模块
let my_module = MyModule;
ctx.register_module(Box::new(my_module));
// 模拟更新循环
for _ in 0..5 {
ctx.update();
}
}
功能说明
re_viewer_context
提供了以下主要功能:
- ViewerContext: 核心上下文对象,用于在查看器模块之间共享数据
- ViewerContextProvider: 模块需要实现的trait,用于接收上下文更新
- 模块管理: 注册和更新多个模块的能力
高级用法
对于更复杂的用例,您可以实现自定义状态管理:
use re_viewer_context::{ViewerContext, ViewerContextProvider};
use std::sync::{Arc, Mutex};
// 共享状态结构
#[derive(Debug, Default)]
struct AppState {
counter: usize,
data: Vec<f32>,
}
// 自定义模块
struct DataProcessor {
state: Arc<Mutex<AppState>>,
}
impl ViewerContextProvider for DataProcessor {
fn on_update(&self, ctx: &mut ViewerContext) {
let mut state = self.state.lock().unwrap();
state.counter += 1;
// 处理一些数据
if state.counter % 10 == 0 {
state.data.push(state.counter as f32);
}
println!("Processed data: {:?}", state.data);
}
}
fn main() {
let shared_state = Arc::new(Mutex::new(AppState::default()));
let mut ctx = ViewerContext::new();
// 注册数据处理模块
let processor = DataProcessor {
state: shared_state.clone(),
};
ctx.register_module(Box::new(processor));
// 模拟长时间运行的应用
for i in 0..100 {
ctx.update();
}
}
完整示例
以下是一个完整的示例,展示了如何使用re_viewer_context创建一个简单的模块化应用:
use re_viewer_context::{ViewerContext, ViewerContextProvider};
use std::sync::{Arc, Mutex};
// 应用状态
#[derive(Debug)]
struct AppState {
frame_count: u32,
messages: Vec<String>,
}
// 日志模块
struct LoggerModule {
state: Arc<Mutex<AppState>>,
}
impl ViewerContextProvider for LoggerModule {
fn on_register(&self, ctx: &mut ViewerContext) {
println!("LoggerModule registered with viewer context");
}
fn on_update(&self, ctx: &mut ViewerContext) {
let mut state = self.state.lock().unwrap();
state.frame_count += 1;
if state.frame_count % 5 == 0 {
let msg = format!("Frame {} processed", state.frame_count);
state.messages.push(msg.clone());
println!("{}", msg);
}
}
}
// 统计模块
struct StatsModule {
state: Arc<Mutex<AppState>>,
}
impl ViewerContextProvider for StatsModule {
fn on_update(&self, ctx: &mut ViewerContext) {
let state = self.state.lock().unwrap();
println!("Current stats - Frames: {}, Messages: {}",
state.frame_count,
state.messages.len());
}
}
fn main() {
// 创建共享状态
let shared_state = Arc::new(Mutex::new(AppState {
frame_count: 0,
messages: Vec::new(),
}));
// 初始化查看器上下文
let mut viewer_ctx = ViewerContext::new();
// 注册模块
viewer_ctx.register_module(Box::new(LoggerModule {
state: shared_state.clone(),
}));
viewer_ctx.register_module(Box::new(StatsModule {
state: shared_state.clone(),
}));
// 主循环
for _ in 0..20 {
viewer_ctx.update();
}
// 打印最终状态
let state = shared_state.lock().unwrap();
println!("Final state: {:?}", state);
}
1 回复
Rust数据分析可视化插件库re_viewer_context使用指南
re_viewer_context
是一个用于Rust数据分析可视化的上下文管理库,它提供了高效的数据查看和管理功能,特别适合需要处理大量数据并实现交互式可视化的应用场景。
主要特性
- 高效的数据存储和检索机制
- 灵活的上下文管理
- 可扩展的插件系统
- 内置常见数据可视化组件
- 支持实时数据更新
安装方法
在Cargo.toml中添加依赖:
[dependencies]
re_viewer_context = "0.1.0" # 请使用最新版本
基本使用方法
1. 创建数据上下文
use re_viewer_context::ViewerContext;
fn main() {
// 创建基础上下文
let mut ctx = ViewerContext::default();
// 添加数据到上下文
ctx.add_data("temperature_data", vec![22.1, 23.4, 24.5, 25.2]);
ctx.add_data("humidity_data", vec![45.0, 47.2, 46.8, 48.1]);
}
2. 使用内置可视化插件
use re_viewer_context::{ViewerContext, PlotPlugin};
fn main() {
let mut ctx = ViewerContext::default();
ctx.add_data("sales", vec![120, 150, 180, 210, 240]);
// 创建并注册绘图插件
let plot_plugin = PlotPlugin::new("sales_plot")
.with_title("Monthly Sales")
.with_x_label("Month")
.with_y_label("Amount");
ctx.register_plugin(plot_plugin);
// 渲染可视化
ctx.render();
}
3. 自定义插件开发
use re_viewer_context::{ViewerContext, Plugin, PluginResponse};
use egui::{Ui, Color32};
struct CustomPlugin {
name: String,
data_key: String,
}
impl Plugin for CustomPlugin {
fn name(&self) -> &str {
&self.name
}
fn show(&mut self, ui: &mut Ui, ctx: &mut ViewerContext) -> PluginResponse {
if let Some(data) = ctx.get_data::<Vec<f32>>(&self.data_key) {
ui.heading(&self.data_key);
let avg = data.iter().sum::<f32>() / data.len() as f32;
ui.label(format!("Average: {:.2}", avg));
// 简单的条形图
for (i, &value) in data.iter().enumerate() {
let bar_height = value * 2.0;
ui.painter().rect_filled(
egui::Rect::from_min_size(
egui::pos2(50.0 + (i as f32 * 30.0), 100.0 - bar_height),
egui::vec2(20.0, bar_height),
egui::Rounding::none(),
Color32::from_rgb(100, 200, 100)
);
}
PluginResponse::Keep
} else {
ui.label(format!("Data '{}' not found", self.data_key));
PluginResponse::Keep
}
}
}
fn main() {
let mut ctx = ViewerContext::default();
ctx.add_data("pressure", vec![1013.2, 1012.8, 1013.5, 1014.1]);
let custom_plugin = CustomPlugin {
name: "Pressure Viewer".to_string(),
data_key: "pressure".to_string(),
};
ctx.register_plugin(custom_plugin);
ctx.render();
}
高级功能
数据更新与实时可视化
use re_viewer_context::{ViewerContext, PlotPlugin};
use std::thread;
use std::time::Duration;
fn main() {
let mut ctx = ViewerContext::default();
let mut data = vec![0.0];
// 设置实时绘图
let plot_plugin = PlotPlugin::new("realtime_plot")
.with_title("Real-time Data")
.with_realtime(true);
ctx.register_plugin(plot_plugin);
// 模拟数据更新线程
thread::spawn(move || {
for i in 1..100 {
thread::sleep(Duration::from_millis(100));
data.push((i as f32).sin() * 10.0);
ctx.update_data("realtime_plot", data.clone());
}
});
// 主线程运行UI
ctx.run();
}
上下文共享与多视图
use re_viewer_context::{ViewerContext, SharedContext};
fn main() {
let ctx = ViewerContext::default();
let shared_ctx = SharedContext::new(ctx);
// 在多个线程中使用共享上下文
let ctx1 = shared_ctx.clone();
thread::spawn(move || {
let mut ctx = ctx1.lock().unwrap();
ctx.add_data("thread1_data", vec![1, 2, 3]);
});
let ctx2 = shared_ctx.clone();
thread::spawn(move || {
let mut ctx = ctx2.lock().unwrap();
ctx.add_data("thread2_data", vec![4, 5, 6]);
});
// 主线程渲染
let mut main_ctx = shared_ctx.lock().unwrap();
main_ctx.render();
}
性能优化技巧
- 对于大型数据集,使用
add_data_with_id
而不是add_data
来避免重复解析 - 在不需要实时更新的情况下,设置
set_realtime(false)
减少渲染开销 - 使用
DataRef
而不是直接复制大数据集 - 对静态数据启用缓存
enable_caching(true)
完整示例demo
下面是一个结合了多个功能的完整示例:
use re_viewer_context::{ViewerContext, Plugin, PluginResponse, PlotPlugin, SharedContext};
use egui::{Ui, Color32};
use std::thread;
use std::time::Duration;
// 自定义插件结构体
struct StatsPlugin {
name: String,
data_key: String,
}
impl Plugin for StatsPlugin {
fn name(&self) -> &str {
&self.name
}
fn show(&mut self, ui: &mut Ui, ctx: &mut ViewerContext) -> PluginResponse {
if let Some(data) = ctx.get_data::<Vec<f32>>(&self.data_key) {
ui.heading(&self.data_key);
// 计算统计信息
let avg = data.iter().sum::<f32>() / data.len() as f32;
let max = data.iter().fold(f32::MIN, |a, &b| a.max(b));
let min = data.iter().fold(f32::MAX, |a, &b| a.min(b));
ui.label(format!("Average: {:.2}", avg));
ui.label(format!("Max: {:.2}", max));
ui.label(format!("Min: {:.2}", min));
PluginResponse::Keep
} else {
ui.label(format!("Data '{}' not found", self.data_key));
PluginResponse::Keep
}
}
}
fn main() {
// 创建共享上下文
let ctx = ViewerContext::default();
let shared_ctx = SharedContext::new(ctx);
// 主线程数据准备
let main_ctx = shared_ctx.clone();
thread::spawn(move || {
let mut ctx = main_ctx.lock().unwrap();
// 添加静态数据
ctx.add_data("population", vec![8.5, 8.8, 9.1, 9.4, 9.7]);
// 注册统计插件
let stats_plugin = StatsPlugin {
name: "Population Stats".to_string(),
data_key: "population".to_string(),
};
ctx.register_plugin(stats_plugin);
// 注册绘图插件
let plot_plugin = PlotPlugin::new("population_plot")
.with_title("Population Growth")
.with_x_label("Year")
.with_y_label("Millions");
ctx.register_plugin(plot_plugin);
});
// 实时数据线程
let realtime_ctx = shared_ctx.clone();
thread::spawn(move || {
let mut data = vec![0.0];
let mut ctx = realtime_ctx.lock().unwrap();
// 注册实时绘图插件
let realtime_plugin = PlotPlugin::new("realtime_data")
.with_title("Real-time Sensor Data")
.with_realtime(true);
ctx.register_plugin(realtime_plugin);
// 模拟实时数据更新
for i in 1..=100 {
thread::sleep(Duration::from_millis(200));
data.push((i as f32 * 0.1).cos() * 5.0 + 10.0);
ctx.update_data("realtime_data", data.clone());
}
});
// 主线程渲染
let mut render_ctx = shared_ctx.lock().unwrap();
render_ctx.run();
}
总结
re_viewer_context
为Rust数据分析可视化提供了强大的上下文管理功能,通过其插件系统可以轻松扩展各种可视化组件。无论是简单的数据绘图还是复杂的实时数据分析系统,都能通过这个库高效实现。