diff --git a/CHANGELOG.md b/CHANGELOG.md index a2bea9184598..e69cb1f6cbe1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -723,7 +723,7 @@ API usage examples: for step in range(0, 64): rr.set_time_sequence("step", step) - rr.log("scalar", rr.Scalar(math.sin(step / 10.0))) + rr.log("scalar", rr.Scalars(math.sin(step / 10.0))) ``` Using `send()` (fast, memory efficient): @@ -779,7 +779,7 @@ API usage examples: for step in 0..64 { rec.set_time_sequence("step", step); - rec.log("scalar", &rerun::Scalar::new((step as f64 / 10.0).sin()))?; + rec.log("scalar", &rerun::Scalars::new((step as f64 / 10.0).sin()))?; } ``` diff --git a/Cargo.lock b/Cargo.lock index 1212ad99f7a3..74ff37c44bf1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2421,13 +2421,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "experimental_multi_scalar" -version = "0.23.0-alpha.1+dev" -dependencies = [ - "rerun", -] - [[package]] name = "extend_viewer_ui" version = "0.23.0-alpha.1+dev" diff --git a/Cargo.toml b/Cargo.toml index 9761429dfc6d..da01570d39c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,6 @@ members = [ "examples/rust/*", "rerun_py", "run_wasm", - "tests/rust/experimental_multi_scalar", "tests/rust/log_benchmark", "tests/rust/plot_dashboard_stress", "tests/rust/roundtrips/*", diff --git a/crates/store/re_chunk_store/src/dataframe.rs b/crates/store/re_chunk_store/src/dataframe.rs index 0a8d7e6bbc5d..abb6123bccb6 100644 --- a/crates/store/re_chunk_store/src/dataframe.rs +++ b/crates/store/re_chunk_store/src/dataframe.rs @@ -297,7 +297,7 @@ pub struct QueryExpression { /// ```text /// view_contents = { /// "world/points": [rr.Position3D, rr.Radius], - /// "metrics": [rr.Scalar] + /// "metrics": [rr.Scalars] /// } /// ``` pub view_contents: Option, diff --git a/crates/store/re_sorbet/src/lib.rs b/crates/store/re_sorbet/src/lib.rs index 1e1a789a0172..60438d1de9bc 100644 --- a/crates/store/re_sorbet/src/lib.rs +++ b/crates/store/re_sorbet/src/lib.rs @@ -25,6 +25,7 @@ mod error; mod index_column_descriptor; mod ipc; mod metadata; +mod migration; mod row_id_column_descriptor; mod sorbet_batch; mod sorbet_columns; @@ -44,6 +45,7 @@ pub use self::{ ArrowBatchMetadata, ArrowFieldMetadata, MetadataExt, MissingFieldMetadata, MissingMetadataKey, }, + migration::migrate_record_batch, row_id_column_descriptor::{RowIdColumnDescriptor, WrongDatatypeError}, sorbet_batch::SorbetBatch, sorbet_columns::SorbetColumnDescriptors, diff --git a/crates/store/re_sorbet/src/migration.rs b/crates/store/re_sorbet/src/migration.rs new file mode 100644 index 000000000000..20e5bbee622a --- /dev/null +++ b/crates/store/re_sorbet/src/migration.rs @@ -0,0 +1,93 @@ +//! Handles migrating old `re_types` to new ones. +//! +//! +use std::collections::BTreeMap; + +use arrow::{ + array::{ArrayRef as ArrowArrayRef, RecordBatch as ArrowRecordBatch, RecordBatchOptions}, + datatypes::{Field as ArrowField, FieldRef as ArrowFieldRef, Schema as ArrowSchema}, +}; + +/// Migrate old renamed types to new types. +pub fn migrate_record_batch(batch: &ArrowRecordBatch) -> ArrowRecordBatch { + re_tracing::profile_function!(); + + struct ArchetypeRename { + new_name: &'static str, + field_renames: BTreeMap<&'static str, &'static str>, + } + + let archetype_renames = BTreeMap::from([ + ( + "rerun.archetypes.Scalar", + ArchetypeRename { + new_name: "rerun.archetypes.Scalars", + field_renames: [("scalar", "scalars")].into(), + }, + ), + ( + "rerun.archetypes.SeriesLine", + ArchetypeRename { + new_name: "rerun.archetypes.SeriesLines", + field_renames: [("color", "colors"), ("width", "widths"), ("name", "names")].into(), + }, + ), + ( + "rerun.archetypes.SeriesPoint", + ArchetypeRename { + new_name: "rerun.archetypes.SeriesPoints", + field_renames: [ + ("color", "colors"), + ("marker", "markers"), + ("name", "names"), + ("marker_size", "marker_sizes"), + ] + .into(), + }, + ), + ]); + + let num_columns = batch.num_columns(); + let mut fields: Vec = Vec::with_capacity(num_columns); + let mut columns: Vec = Vec::with_capacity(num_columns); + + for (field, array) in itertools::izip!(batch.schema().fields(), batch.columns()) { + let mut metadata = field.metadata().clone(); + if let Some(archetype) = metadata.get_mut("rerun.archetype") { + if let Some(archetype_rename) = archetype_renames.get(archetype.as_str()) { + re_log::debug_once!( + "Migrating {archetype:?} to {:?}…", + archetype_rename.new_name + ); + + // Rename archetype: + *archetype = archetype_rename.new_name.to_owned(); + + // Renmame fields: + if let Some(archetype_field) = metadata.get_mut("rerun.archetype_field") { + if let Some(new_field_name) = + archetype_rename.field_renames.get(archetype_field.as_str()) + { + *archetype_field = (*new_field_name).to_owned(); + } + } + } + } + + let field = ArrowField::clone(field.as_ref()) + .clone() + .with_metadata(metadata); + + fields.push(field.into()); + columns.push(array.clone()); + } + + let schema = ArrowSchema::new_with_metadata(fields, batch.schema().metadata.clone()); + + ArrowRecordBatch::try_new_with_options( + schema.into(), + columns, + &RecordBatchOptions::default().with_row_count(Some(batch.num_rows())), + ) + .expect("Can't fail") +} diff --git a/crates/store/re_sorbet/src/sorbet_batch.rs b/crates/store/re_sorbet/src/sorbet_batch.rs index f06ec89a9d4b..94a109f8b36a 100644 --- a/crates/store/re_sorbet/src/sorbet_batch.rs +++ b/crates/store/re_sorbet/src/sorbet_batch.rs @@ -155,6 +155,8 @@ impl From<&SorbetBatch> for ArrowRecordBatch { impl SorbetBatch { /// Will automatically wrap data columns in `ListArrays` if they are not already. + /// + /// Will also migrate old types to new types. pub fn try_from_record_batch( batch: &ArrowRecordBatch, batch_type: crate::BatchType, @@ -162,6 +164,7 @@ impl SorbetBatch { re_tracing::profile_function!(); let batch = make_all_data_columns_list_arrays(batch); + let batch = crate::migrate_record_batch(&batch); let sorbet_schema = SorbetSchema::try_from(batch.schema_ref().as_ref())?; diff --git a/crates/store/re_types/definitions/rerun/archetypes.fbs b/crates/store/re_types/definitions/rerun/archetypes.fbs index 60a3f9bf126e..ba888f784b92 100644 --- a/crates/store/re_types/definitions/rerun/archetypes.fbs +++ b/crates/store/re_types/definitions/rerun/archetypes.fbs @@ -27,9 +27,12 @@ include "./archetypes/points2d.fbs"; include "./archetypes/points3d.fbs"; include "./archetypes/recording_properties.fbs"; include "./archetypes/scalar.fbs"; +include "./archetypes/scalars.fbs"; include "./archetypes/segmentation_image.fbs"; include "./archetypes/series_line.fbs"; +include "./archetypes/series_lines.fbs"; include "./archetypes/series_point.fbs"; +include "./archetypes/series_points.fbs"; include "./archetypes/tensor.fbs"; include "./archetypes/text_document.fbs"; include "./archetypes/text_log.fbs"; diff --git a/crates/store/re_types/definitions/rerun/archetypes/scalar.fbs b/crates/store/re_types/definitions/rerun/archetypes/scalar.fbs index e135565cb55b..d343a4f65573 100644 --- a/crates/store/re_types/definitions/rerun/archetypes/scalar.fbs +++ b/crates/store/re_types/definitions/rerun/archetypes/scalar.fbs @@ -1,22 +1,21 @@ namespace rerun.archetypes; -// --- - /// A double-precision scalar, e.g. for use for time-series plots. /// /// The current timeline value will be used for the time/X-axis, hence scalars -/// cannot be static. +/// should not be static. /// /// When used to produce a plot, this archetype is used to provide the data that -/// is referenced by [archetypes.SeriesLine] or [archetypes.SeriesPoint]. You can do +/// is referenced by [archetypes.SeriesLines] or [archetypes.SeriesPoints]. You can do /// this by logging both archetypes to the same path, or alternatively configuring /// the plot-specific archetypes through the blueprint. /// -/// \example archetypes/scalar_simple !api title="Simple line plot" image="https://static.rerun.io/scalar_simple/8bcc92f56268739f8cd24d60d1fe72a655f62a46/1200w.png" -/// \example archetypes/scalar_multiple_plots !api title="Multiple time series plots" image="https://static.rerun.io/scalar_multiple/15845c2a348f875248fbd694e03eabd922741c4c/1200w.png" -/// \example archetypes/scalar_row_updates title="Update a scalar over time" image="https://static.rerun.io/transform3d_column_updates/2b7ccfd29349b2b107fcf7eb8a1291a92cf1cafc/1200w.png" -/// \example archetypes/scalar_column_updates title="Update a scalar over time, in a single operation" image="https://static.rerun.io/transform3d_column_updates/2b7ccfd29349b2b107fcf7eb8a1291a92cf1cafc/1200w.png" +/// \example archetypes/scalars_simple !api title="Simple line plot" image="https://static.rerun.io/scalar_simple/8bcc92f56268739f8cd24d60d1fe72a655f62a46/1200w.png" +/// \example archetypes/scalars_multiple_plots !api title="Multiple time series plots" image="https://static.rerun.io/scalar_multiple/15845c2a348f875248fbd694e03eabd922741c4c/1200w.png" +/// \example archetypes/scalars_row_updates title="Update a scalar over time" image="https://static.rerun.io/transform3d_column_updates/2b7ccfd29349b2b107fcf7eb8a1291a92cf1cafc/1200w.png" +/// \example archetypes/scalars_column_updates title="Update a scalar over time, in a single operation" image="https://static.rerun.io/transform3d_column_updates/2b7ccfd29349b2b107fcf7eb8a1291a92cf1cafc/1200w.png" table Scalar ( + "attr.rerun.deprecated": "Use `Scalars` instead.", "attr.rust.derive": "PartialEq", "attr.docs.category": "Plotting", "attr.docs.view_types": "TimeSeriesView" diff --git a/crates/store/re_types/definitions/rerun/archetypes/scalars.fbs b/crates/store/re_types/definitions/rerun/archetypes/scalars.fbs new file mode 100644 index 000000000000..706d87d554c0 --- /dev/null +++ b/crates/store/re_types/definitions/rerun/archetypes/scalars.fbs @@ -0,0 +1,34 @@ +namespace rerun.archetypes; + +/// One or more double-precision scalar values, e.g. for use for time-series plots. +/// +/// The current timeline value will be used for the time/X-axis, hence scalars +/// should not be static. +/// Number of scalars per timestamp is expected to be the same over time. +/// +/// When used to produce a plot, this archetype is used to provide the data that +/// is referenced by [archetypes.SeriesLines] or [archetypes.SeriesPoints]. You can do +/// this by logging both archetypes to the same path, or alternatively configuring +/// the plot-specific archetypes through the blueprint. +/// +/// \example archetypes/scalars_simple !api title="Simple line plot" image="https://static.rerun.io/scalar_simple/8bcc92f56268739f8cd24d60d1fe72a655f62a46/1200w.png" +/// \example archetypes/scalars_multiple_plots !api title="Multiple time series plots" image="https://static.rerun.io/scalar_multiple/15845c2a348f875248fbd694e03eabd922741c4c/1200w.png" +/// \example archetypes/scalars_row_updates title="Update a scalar over time" image="https://static.rerun.io/transform3d_column_updates/2b7ccfd29349b2b107fcf7eb8a1291a92cf1cafc/1200w.png" +/// \example archetypes/scalars_column_updates title="Update a scalar over time, in a single operation" image="https://static.rerun.io/transform3d_column_updates/2b7ccfd29349b2b107fcf7eb8a1291a92cf1cafc/1200w.png" +table Scalars ( + "attr.docs.unreleased", + "attr.rust.derive": "PartialEq", + "attr.docs.category": "Plotting", + "attr.docs.view_types": "TimeSeriesView" +) { + // --- Required --- + + /// The scalar values to log. + scalars: [rerun.components.Scalar] ("attr.rerun.component_required", order: 1000); + + // --- Recommended --- + + // --- Optional --- + + // TODO(#1289): Support labeling points. +} diff --git a/crates/store/re_types/definitions/rerun/archetypes/segmentation_image.fbs b/crates/store/re_types/definitions/rerun/archetypes/segmentation_image.fbs index 8aa0e2048c28..ce622d191a26 100644 --- a/crates/store/re_types/definitions/rerun/archetypes/segmentation_image.fbs +++ b/crates/store/re_types/definitions/rerun/archetypes/segmentation_image.fbs @@ -1,6 +1,5 @@ namespace rerun.archetypes; - /// An image made up of integer [components.ClassId]s. /// /// Each pixel corresponds to a [components.ClassId] that will be mapped to a color based on annotation context. diff --git a/crates/store/re_types/definitions/rerun/archetypes/series_line.fbs b/crates/store/re_types/definitions/rerun/archetypes/series_line.fbs index 3a7c06004364..40e02b536584 100644 --- a/crates/store/re_types/definitions/rerun/archetypes/series_line.fbs +++ b/crates/store/re_types/definitions/rerun/archetypes/series_line.fbs @@ -1,15 +1,14 @@ namespace rerun.archetypes; -// --- - /// Define the style properties for a line series in a chart. /// /// This archetype only provides styling information and should be logged as static /// when possible. The underlying data needs to be logged to the same entity-path using -/// [archetypes.Scalar]. +/// [archetypes.Scalars]. /// -/// \example archetypes/series_line_style title="Line series" image="https://static.rerun.io/series_line_style/d2616d98b1e46bdb85849b8669154fdf058e3453/1200w.png" +/// \example archetypes/series_lines_style title="Line series" image="https://static.rerun.io/series_line_style/d2616d98b1e46bdb85849b8669154fdf058e3453/1200w.png" table SeriesLine ( + "attr.rerun.deprecated": "Use `SeriesLines` instead.", "attr.docs.category": "Plotting", "attr.docs.view_types": "TimeSeriesView" ) { diff --git a/crates/store/re_types/definitions/rerun/archetypes/series_lines.fbs b/crates/store/re_types/definitions/rerun/archetypes/series_lines.fbs new file mode 100644 index 000000000000..83969896f689 --- /dev/null +++ b/crates/store/re_types/definitions/rerun/archetypes/series_lines.fbs @@ -0,0 +1,62 @@ +namespace rerun.archetypes; + +/// Define the style properties for one or more line series in a chart. +/// +/// This archetype only provides styling information. +/// Changes over time are supported for most but not all its fields (see respective fields for details), +/// it's generally recommended to log this type as static. +/// +/// The underlying data needs to be logged to the same entity-path using [archetypes.Scalars]. +/// Dimensionality of the scalar arrays logged at each time point is assumed to be the same over time. +/// +/// \example archetypes/series_lines_style title="Line series" image="https://static.rerun.io/series_line_style/d2616d98b1e46bdb85849b8669154fdf058e3453/1200w.png" +table SeriesLines ( + "attr.docs.unreleased", + "attr.docs.category": "Plotting", + "attr.docs.view_types": "TimeSeriesView" +) { + // --- Required --- + + // --- Optional --- + + // TODO(#8368, #9334): Once it's trivial to override how scalars for a plot are sourced, + // we should make it explicit that the `SeriesLines`/`SeriesPoints` visualizers require + // scalars as an input. + // Doing so right now would break the model of how time series logging works too much: + // This is a case where we want to encourage data <-> styling separation more than elsewhere, + // so it's important to make keeping it separate easy. + //scalars: [rerun.components.Scalar]; + + /// Color for the corresponding series. + /// + /// May change over time, but can cause discontinuities in the line. + colors: [rerun.components.Color] ("attr.rerun.component_optional", nullable, order: 1000); + + /// Stroke width for the corresponding series. + /// + /// May change over time, but can cause discontinuities in the line. + widths: [rerun.components.StrokeWidth] ("attr.rerun.component_optional", nullable, order: 2000); + + /// Display name of the series. + /// + /// Used in the legend. Expected to be unchanging over time. + names: [rerun.components.Name] ("attr.rerun.component_optional", nullable, order: 3000); + + /// Which lines are visible. + /// + /// If not set, all line series on this entity are visible. + /// Unlike with the regular visibility property of the entire entity, any series that is hidden + /// via this property will still be visible in the legend. + /// + /// May change over time, but can cause discontinuities in the line. + visible_series: [rerun.components.SeriesVisible] ("attr.rerun.component_optional", nullable, order: 3100); + + /// Configures the zoom-dependent scalar aggregation. + /// + /// This is done only if steps on the X axis go below a single pixel, + /// i.e. a single pixel covers more than one tick worth of data. It can greatly improve performance + /// (and readability) in such situations as it prevents overdraw. + /// + /// Expected to be unchanging over time. + aggregation_policy: rerun.components.AggregationPolicy ("attr.rerun.component_optional", nullable, order: 4000); +} diff --git a/crates/store/re_types/definitions/rerun/archetypes/series_point.fbs b/crates/store/re_types/definitions/rerun/archetypes/series_point.fbs index bbadf1091914..00354e594d0d 100644 --- a/crates/store/re_types/definitions/rerun/archetypes/series_point.fbs +++ b/crates/store/re_types/definitions/rerun/archetypes/series_point.fbs @@ -1,15 +1,14 @@ namespace rerun.archetypes; -// --- - /// Define the style properties for a point series in a chart. /// /// This archetype only provides styling information and should be logged as static /// when possible. The underlying data needs to be logged to the same entity-path using -/// [archetypes.Scalar]. +/// [archetypes.Scalars]. /// -/// \example archetypes/series_point_style title="Point series" image="https://static.rerun.io/series_point_style/82207a705da6c086b28ce161db1db9e8b12258b7/1200w.png" +/// \example archetypes/series_points_style title="Point series" image="https://static.rerun.io/series_point_style/82207a705da6c086b28ce161db1db9e8b12258b7/1200w.png" table SeriesPoint ( + "attr.rerun.deprecated": "Use `SeriesPoints` instead.", "attr.docs.category": "Plotting", "attr.docs.view_types": "TimeSeriesView" ) { diff --git a/crates/store/re_types/definitions/rerun/archetypes/series_points.fbs b/crates/store/re_types/definitions/rerun/archetypes/series_points.fbs new file mode 100644 index 000000000000..0d0b411a89c3 --- /dev/null +++ b/crates/store/re_types/definitions/rerun/archetypes/series_points.fbs @@ -0,0 +1,58 @@ +namespace rerun.archetypes; + +/// Define the style properties for one or more point series (scatter plot) in a chart. +/// +/// This archetype only provides styling information. +/// Changes over time are supported for most but not all its fields (see respective fields for details), +/// it's generally recommended to log this type as static. +/// +/// The underlying data needs to be logged to the same entity-path using [archetypes.Scalars]. +/// Dimensionality of the scalar arrays logged at each time point is assumed to be the same over time. +/// +/// \example archetypes/series_points_style title="Point series" image="https://static.rerun.io/series_point_style/82207a705da6c086b28ce161db1db9e8b12258b7/1200w.png" +table SeriesPoints ( + "attr.docs.unreleased", + "attr.docs.category": "Plotting", + "attr.docs.view_types": "TimeSeriesView" +) { + // --- Required --- + + // --- Optional --- + + // TODO(#8368, #9334): Once it's trivial to override how scalars for a plot are sourced, + // we should make it explicit that the `SeriesLines`/`SeriesPoints` visualizers require + // scalars as an input. + // Doing so right now would break the model of how time series logging works too much: + // This is a case where we want to encourage data <-> styling separation more than elsewhere, + // so it's important to make keeping it separate easy. + //scalars: [rerun.components.Scalar]; + + /// Color for the corresponding series. + /// + /// May change over time, but can cause discontinuities in the line. + colors: [rerun.components.Color] ("attr.rerun.component_optional", nullable, order: 1000); + + /// What shape to use to represent the point + /// + /// May change over time. + markers: [rerun.components.MarkerShape] ("attr.rerun.component_optional", nullable, order: 2000); + + /// Display name of the series. + /// + /// Used in the legend. Expected to be unchanging over time. + names: [rerun.components.Name] ("attr.rerun.component_optional", nullable, order: 3000); + + /// Which lines are visible. + /// + /// If not set, all line series on this entity are visible. + /// Unlike with the regular visibility property of the entire entity, any series that is hidden + /// via this property will still be visible in the legend. + /// + /// May change over time. + visible_series: [rerun.components.SeriesVisible] ("attr.rerun.component_optional", nullable, order: 3100); + + /// Sizes of the markers. + /// + /// May change over time. + marker_sizes: [rerun.components.MarkerSize] ("attr.rerun.component_optional", nullable, order: 4000); +} diff --git a/crates/store/re_types/definitions/rerun/blueprint/views/time_series.fbs b/crates/store/re_types/definitions/rerun/blueprint/views/time_series.fbs index 0b56bf20f7fd..2f3b2f298c5a 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/views/time_series.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/views/time_series.fbs @@ -1,6 +1,6 @@ namespace rerun.blueprint.views; -/// A time series view for scalars over time, for use with [archetypes.Scalar]. +/// A time series view for scalars over time, for use with [archetypes.Scalars]. /// /// \example views/timeseries title="Use a blueprint to customize a TimeSeriesView." image="https://static.rerun.io/timeseries_view/c87150647feb413627fdb8563afe33b39d7dbf57/1200w.png" table TimeSeriesView ( diff --git a/crates/store/re_types/src/archetypes/.gitattributes b/crates/store/re_types/src/archetypes/.gitattributes index 3655e439da33..824488ac63aa 100644 --- a/crates/store/re_types/src/archetypes/.gitattributes +++ b/crates/store/re_types/src/archetypes/.gitattributes @@ -28,9 +28,12 @@ points2d.rs linguist-generated=true points3d.rs linguist-generated=true recording_properties.rs linguist-generated=true scalar.rs linguist-generated=true +scalars.rs linguist-generated=true segmentation_image.rs linguist-generated=true series_line.rs linguist-generated=true +series_lines.rs linguist-generated=true series_point.rs linguist-generated=true +series_points.rs linguist-generated=true tensor.rs linguist-generated=true text_document.rs linguist-generated=true text_log.rs linguist-generated=true diff --git a/crates/store/re_types/src/archetypes/mod.rs b/crates/store/re_types/src/archetypes/mod.rs index 925717934b4a..a0c84095f80c 100644 --- a/crates/store/re_types/src/archetypes/mod.rs +++ b/crates/store/re_types/src/archetypes/mod.rs @@ -43,10 +43,14 @@ mod points3d; mod points3d_ext; mod recording_properties; mod scalar; +mod scalars; +mod scalars_ext; mod segmentation_image; mod segmentation_image_ext; mod series_line; +mod series_lines; mod series_point; +mod series_points; mod tensor; mod tensor_ext; mod text_document; @@ -83,13 +87,20 @@ pub use self::pinhole::Pinhole; pub use self::points2d::Points2D; pub use self::points3d::Points3D; pub use self::recording_properties::RecordingProperties; -pub use self::scalar::Scalar; +pub use self::scalars::Scalars; pub use self::segmentation_image::SegmentationImage; -pub use self::series_line::SeriesLine; -pub use self::series_point::SeriesPoint; +pub use self::series_lines::SeriesLines; +pub use self::series_points::SeriesPoints; pub use self::tensor::Tensor; pub use self::text_document::TextDocument; pub use self::text_log::TextLog; pub use self::transform3d::Transform3D; pub use self::video_frame_reference::VideoFrameReference; pub use self::view_coordinates::ViewCoordinates; + +#[expect(deprecated)] +pub use self::scalar::Scalar; +#[expect(deprecated)] +pub use self::series_line::SeriesLine; +#[expect(deprecated)] +pub use self::series_point::SeriesPoint; diff --git a/crates/store/re_types/src/archetypes/scalar.rs b/crates/store/re_types/src/archetypes/scalar.rs index 9579847781a8..2e1a53beed6b 100644 --- a/crates/store/re_types/src/archetypes/scalar.rs +++ b/crates/store/re_types/src/archetypes/scalar.rs @@ -11,6 +11,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_lines)] +#![expect(deprecated)] use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; @@ -21,10 +22,10 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Archetype**: A double-precision scalar, e.g. for use for time-series plots. /// /// The current timeline value will be used for the time/X-axis, hence scalars -/// cannot be static. +/// should not be static. /// /// When used to produce a plot, this archetype is used to provide the data that -/// is referenced by [`archetypes::SeriesLine`][crate::archetypes::SeriesLine] or [`archetypes::SeriesPoint`][crate::archetypes::SeriesPoint]. You can do +/// is referenced by [`archetypes::SeriesLines`][crate::archetypes::SeriesLines] or [`archetypes::SeriesPoints`][crate::archetypes::SeriesPoints]. You can do /// this by logging both archetypes to the same path, or alternatively configuring /// the plot-specific archetypes through the blueprint. /// @@ -37,7 +38,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// for step in 0..64 { /// rec.set_time_sequence("step", step); -/// rec.log("scalars", &rerun::Scalar::new((step as f64 / 10.0).sin()))?; +/// rec.log("scalars", &rerun::Scalars::one((step as f64 / 10.0).sin()))?; /// } /// /// Ok(()) @@ -66,9 +67,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// rec.send_columns( /// "scalars", /// [times], -/// rerun::Scalar::update_fields() -/// .with_many_scalar(scalars) -/// .columns_of_unit_batches()?, +/// rerun::Scalars::new(scalars).columns_of_unit_batches()?, /// )?; /// /// Ok(()) @@ -84,6 +83,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// #[derive(Clone, Debug, PartialEq, Default)] +#[deprecated(note = "Use `Scalars` instead.")] pub struct Scalar { /// The scalar value to log. pub scalar: Option, diff --git a/crates/store/re_types/src/archetypes/scalars.rs b/crates/store/re_types/src/archetypes/scalars.rs new file mode 100644 index 000000000000..2ea289ed58b8 --- /dev/null +++ b/crates/store/re_types/src/archetypes/scalars.rs @@ -0,0 +1,290 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/store/re_types/definitions/rerun/archetypes/scalars.fbs". + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::map_flatten)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] + +use ::re_types_core::try_serialize_field; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch as _, SerializedComponentBatch}; +use ::re_types_core::{ComponentDescriptor, ComponentName}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Archetype**: One or more double-precision scalar values, e.g. for use for time-series plots. +/// +/// The current timeline value will be used for the time/X-axis, hence scalars +/// should not be static. +/// Number of scalars per timestamp is expected to be the same over time. +/// +/// When used to produce a plot, this archetype is used to provide the data that +/// is referenced by [`archetypes::SeriesLines`][crate::archetypes::SeriesLines] or [`archetypes::SeriesPoints`][crate::archetypes::SeriesPoints]. You can do +/// this by logging both archetypes to the same path, or alternatively configuring +/// the plot-specific archetypes through the blueprint. +/// +/// ## Examples +/// +/// ### Update a scalar over time +/// ```ignore +/// fn main() -> Result<(), Box> { +/// let rec = rerun::RecordingStreamBuilder::new("rerun_example_scalar_row_updates").spawn()?; +/// +/// for step in 0..64 { +/// rec.set_time_sequence("step", step); +/// rec.log("scalars", &rerun::Scalars::one((step as f64 / 10.0).sin()))?; +/// } +/// +/// Ok(()) +/// } +/// ``` +///
+/// +/// +/// +/// +/// +/// +/// +///
+/// +/// ### Update a scalar over time, in a single operation +/// ```ignore +/// use rerun::TimeColumn; +/// +/// fn main() -> Result<(), Box> { +/// let rec = rerun::RecordingStreamBuilder::new("rerun_example_scalar_column_updates").spawn()?; +/// +/// let times = TimeColumn::new_sequence("step", 0..64); +/// let scalars = (0..64).map(|step| (step as f64 / 10.0).sin()); +/// +/// rec.send_columns( +/// "scalars", +/// [times], +/// rerun::Scalars::new(scalars).columns_of_unit_batches()?, +/// )?; +/// +/// Ok(()) +/// } +/// ``` +///
+/// +/// +/// +/// +/// +/// +/// +///
+#[derive(Clone, Debug, PartialEq, Default)] +pub struct Scalars { + /// The scalar values to log. + pub scalars: Option, +} + +impl Scalars { + /// Returns the [`ComponentDescriptor`] for [`Self::scalars`]. + #[inline] + pub fn descriptor_scalars() -> ComponentDescriptor { + ComponentDescriptor { + archetype_name: Some("rerun.archetypes.Scalars".into()), + component_name: "rerun.components.Scalar".into(), + archetype_field_name: Some("scalars".into()), + } + } + + /// Returns the [`ComponentDescriptor`] for the associated indicator component. + #[inline] + pub fn descriptor_indicator() -> ComponentDescriptor { + ComponentDescriptor { + archetype_name: Some("rerun.archetypes.Scalars".into()), + component_name: "rerun.components.ScalarsIndicator".into(), + archetype_field_name: None, + } + } +} + +static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 1usize]> = + once_cell::sync::Lazy::new(|| [Scalars::descriptor_scalars()]); + +static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 1usize]> = + once_cell::sync::Lazy::new(|| [Scalars::descriptor_indicator()]); + +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 0usize]> = + once_cell::sync::Lazy::new(|| []); + +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 2usize]> = + once_cell::sync::Lazy::new(|| { + [ + Scalars::descriptor_scalars(), + Scalars::descriptor_indicator(), + ] + }); + +impl Scalars { + /// The total number of components in the archetype: 1 required, 1 recommended, 0 optional + pub const NUM_COMPONENTS: usize = 2usize; +} + +/// Indicator component for the [`Scalars`] [`::re_types_core::Archetype`] +pub type ScalarsIndicator = ::re_types_core::GenericIndicatorComponent; + +impl ::re_types_core::Archetype for Scalars { + type Indicator = ScalarsIndicator; + + #[inline] + fn name() -> ::re_types_core::ArchetypeName { + "rerun.archetypes.Scalars".into() + } + + #[inline] + fn display_name() -> &'static str { + "Scalars" + } + + #[inline] + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + ScalarsIndicator::DEFAULT.serialized().unwrap() + } + + #[inline] + fn required_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + REQUIRED_COMPONENTS.as_slice().into() + } + + #[inline] + fn recommended_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + RECOMMENDED_COMPONENTS.as_slice().into() + } + + #[inline] + fn optional_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + OPTIONAL_COMPONENTS.as_slice().into() + } + + #[inline] + fn all_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + ALL_COMPONENTS.as_slice().into() + } + + #[inline] + fn from_arrow_components( + arrow_data: impl IntoIterator, + ) -> DeserializationResult { + re_tracing::profile_function!(); + use ::re_types_core::{Loggable as _, ResultExt as _}; + let arrays_by_descr: ::nohash_hasher::IntMap<_, _> = arrow_data.into_iter().collect(); + let scalars = arrays_by_descr + .get(&Self::descriptor_scalars()) + .map(|array| SerializedComponentBatch::new(array.clone(), Self::descriptor_scalars())); + Ok(Self { scalars }) + } +} + +impl ::re_types_core::AsComponents for Scalars { + #[inline] + fn as_serialized_batches(&self) -> Vec { + use ::re_types_core::Archetype as _; + [Some(Self::indicator()), self.scalars.clone()] + .into_iter() + .flatten() + .collect() + } +} + +impl ::re_types_core::ArchetypeReflectionMarker for Scalars {} + +impl Scalars { + /// Create a new `Scalars`. + #[inline] + pub fn new(scalars: impl IntoIterator>) -> Self { + Self { + scalars: try_serialize_field(Self::descriptor_scalars(), scalars), + } + } + + /// Update only some specific fields of a `Scalars`. + #[inline] + pub fn update_fields() -> Self { + Self::default() + } + + /// Clear all the fields of a `Scalars`. + #[inline] + pub fn clear_fields() -> Self { + use ::re_types_core::Loggable as _; + Self { + scalars: Some(SerializedComponentBatch::new( + crate::components::Scalar::arrow_empty(), + Self::descriptor_scalars(), + )), + } + } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [self + .scalars + .map(|scalars| scalars.partitioned(_lengths.clone())) + .transpose()?]; + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) + } + + /// Helper to partition the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling [`Self::columns`] with `std::iter::take(1).repeat(n)`, + /// where `n` is automatically guessed. + #[inline] + pub fn columns_of_unit_batches( + self, + ) -> SerializationResult> { + let len_scalars = self.scalars.as_ref().map(|b| b.array.len()); + let len = None.or(len_scalars).unwrap_or(0); + self.columns(std::iter::repeat(1).take(len)) + } + + /// The scalar values to log. + #[inline] + pub fn with_scalars( + mut self, + scalars: impl IntoIterator>, + ) -> Self { + self.scalars = try_serialize_field(Self::descriptor_scalars(), scalars); + self + } +} + +impl ::re_byte_size::SizeBytes for Scalars { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.scalars.heap_size_bytes() + } +} diff --git a/crates/store/re_types/src/archetypes/scalars_ext.rs b/crates/store/re_types/src/archetypes/scalars_ext.rs new file mode 100644 index 000000000000..aee938a55302 --- /dev/null +++ b/crates/store/re_types/src/archetypes/scalars_ext.rs @@ -0,0 +1,6 @@ +impl crate::archetypes::Scalars { + /// Constructor for a single scalar. + pub fn one(value: impl Into) -> Self { + Self::new([value.into()]) + } +} diff --git a/crates/store/re_types/src/archetypes/series_line.rs b/crates/store/re_types/src/archetypes/series_line.rs index 3cb7dec3e39d..5c2a63ebd97f 100644 --- a/crates/store/re_types/src/archetypes/series_line.rs +++ b/crates/store/re_types/src/archetypes/series_line.rs @@ -11,6 +11,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_lines)] +#![expect(deprecated)] use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; @@ -22,7 +23,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// This archetype only provides styling information and should be logged as static /// when possible. The underlying data needs to be logged to the same entity-path using -/// [`archetypes::Scalar`][crate::archetypes::Scalar]. +/// [`archetypes::Scalars`][crate::archetypes::Scalars]. /// /// ## Example /// @@ -36,25 +37,25 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// // Log two lines series under a shared root so that they show in the same plot by default. /// rec.log_static( /// "trig/sin", -/// &rerun::SeriesLine::new() -/// .with_color([255, 0, 0]) -/// .with_name("sin(0.01t)") -/// .with_width(2.0), +/// &rerun::SeriesLines::new() +/// .with_colors([[255, 0, 0]]) +/// .with_names(["sin(0.01t)"]) +/// .with_widths([2.0]), /// )?; /// rec.log_static( /// "trig/cos", -/// &rerun::SeriesLine::new() -/// .with_color([0, 255, 0]) -/// .with_name("cos(0.01t)") -/// .with_width(4.0), +/// &rerun::SeriesLines::new() +/// .with_colors([[0, 255, 0]]) +/// .with_names(["cos(0.01t)"]) +/// .with_widths([4.0]), /// )?; /// /// for t in 0..((std::f32::consts::TAU * 2.0 * 100.0) as i64) { /// rec.set_time_sequence("step", t); /// /// // Log two time series under a shared root so that they show in the same plot by default. -/// rec.log("trig/sin", &rerun::Scalar::new((t as f64 / 100.0).sin()))?; -/// rec.log("trig/cos", &rerun::Scalar::new((t as f64 / 100.0).cos()))?; +/// rec.log("trig/sin", &rerun::Scalars::one((t as f64 / 100.0).sin()))?; +/// rec.log("trig/cos", &rerun::Scalars::one((t as f64 / 100.0).cos()))?; /// } /// /// Ok(()) @@ -70,6 +71,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// #[derive(Clone, Debug, Default)] +#[deprecated(note = "Use `SeriesLines` instead.")] pub struct SeriesLine { /// Color for the corresponding series. pub color: Option, diff --git a/crates/store/re_types/src/archetypes/series_lines.rs b/crates/store/re_types/src/archetypes/series_lines.rs new file mode 100644 index 000000000000..5cf6b52725b3 --- /dev/null +++ b/crates/store/re_types/src/archetypes/series_lines.rs @@ -0,0 +1,512 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/store/re_types/definitions/rerun/archetypes/series_lines.fbs". + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::map_flatten)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] + +use ::re_types_core::try_serialize_field; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch as _, SerializedComponentBatch}; +use ::re_types_core::{ComponentDescriptor, ComponentName}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Archetype**: Define the style properties for one or more line series in a chart. +/// +/// This archetype only provides styling information. +/// Changes over time are supported for most but not all its fields (see respective fields for details), +/// it's generally recommended to log this type as static. +/// +/// The underlying data needs to be logged to the same entity-path using [`archetypes::Scalars`][crate::archetypes::Scalars]. +/// Dimensionality of the scalar arrays logged at each time point is assumed to be the same over time. +/// +/// ## Example +/// +/// ### Line series +/// ```ignore +/// fn main() -> Result<(), Box> { +/// let rec = rerun::RecordingStreamBuilder::new("rerun_example_series_line_style").spawn()?; +/// +/// // Set up plot styling: +/// // They are logged static as they don't change over time and apply to all timelines. +/// // Log two lines series under a shared root so that they show in the same plot by default. +/// rec.log_static( +/// "trig/sin", +/// &rerun::SeriesLines::new() +/// .with_colors([[255, 0, 0]]) +/// .with_names(["sin(0.01t)"]) +/// .with_widths([2.0]), +/// )?; +/// rec.log_static( +/// "trig/cos", +/// &rerun::SeriesLines::new() +/// .with_colors([[0, 255, 0]]) +/// .with_names(["cos(0.01t)"]) +/// .with_widths([4.0]), +/// )?; +/// +/// for t in 0..((std::f32::consts::TAU * 2.0 * 100.0) as i64) { +/// rec.set_time_sequence("step", t); +/// +/// // Log two time series under a shared root so that they show in the same plot by default. +/// rec.log("trig/sin", &rerun::Scalars::one((t as f64 / 100.0).sin()))?; +/// rec.log("trig/cos", &rerun::Scalars::one((t as f64 / 100.0).cos()))?; +/// } +/// +/// Ok(()) +/// } +/// ``` +///
+/// +/// +/// +/// +/// +/// +/// +///
+#[derive(Clone, Debug, Default)] +pub struct SeriesLines { + /// Color for the corresponding series. + /// + /// May change over time, but can cause discontinuities in the line. + pub colors: Option, + + /// Stroke width for the corresponding series. + /// + /// May change over time, but can cause discontinuities in the line. + pub widths: Option, + + /// Display name of the series. + /// + /// Used in the legend. Expected to be unchanging over time. + pub names: Option, + + /// Which lines are visible. + /// + /// If not set, all line series on this entity are visible. + /// Unlike with the regular visibility property of the entire entity, any series that is hidden + /// via this property will still be visible in the legend. + /// + /// May change over time, but can cause discontinuities in the line. + pub visible_series: Option, + + /// Configures the zoom-dependent scalar aggregation. + /// + /// This is done only if steps on the X axis go below a single pixel, + /// i.e. a single pixel covers more than one tick worth of data. It can greatly improve performance + /// (and readability) in such situations as it prevents overdraw. + /// + /// Expected to be unchanging over time. + pub aggregation_policy: Option, +} + +impl SeriesLines { + /// Returns the [`ComponentDescriptor`] for [`Self::colors`]. + #[inline] + pub fn descriptor_colors() -> ComponentDescriptor { + ComponentDescriptor { + archetype_name: Some("rerun.archetypes.SeriesLines".into()), + component_name: "rerun.components.Color".into(), + archetype_field_name: Some("colors".into()), + } + } + + /// Returns the [`ComponentDescriptor`] for [`Self::widths`]. + #[inline] + pub fn descriptor_widths() -> ComponentDescriptor { + ComponentDescriptor { + archetype_name: Some("rerun.archetypes.SeriesLines".into()), + component_name: "rerun.components.StrokeWidth".into(), + archetype_field_name: Some("widths".into()), + } + } + + /// Returns the [`ComponentDescriptor`] for [`Self::names`]. + #[inline] + pub fn descriptor_names() -> ComponentDescriptor { + ComponentDescriptor { + archetype_name: Some("rerun.archetypes.SeriesLines".into()), + component_name: "rerun.components.Name".into(), + archetype_field_name: Some("names".into()), + } + } + + /// Returns the [`ComponentDescriptor`] for [`Self::visible_series`]. + #[inline] + pub fn descriptor_visible_series() -> ComponentDescriptor { + ComponentDescriptor { + archetype_name: Some("rerun.archetypes.SeriesLines".into()), + component_name: "rerun.components.SeriesVisible".into(), + archetype_field_name: Some("visible_series".into()), + } + } + + /// Returns the [`ComponentDescriptor`] for [`Self::aggregation_policy`]. + #[inline] + pub fn descriptor_aggregation_policy() -> ComponentDescriptor { + ComponentDescriptor { + archetype_name: Some("rerun.archetypes.SeriesLines".into()), + component_name: "rerun.components.AggregationPolicy".into(), + archetype_field_name: Some("aggregation_policy".into()), + } + } + + /// Returns the [`ComponentDescriptor`] for the associated indicator component. + #[inline] + pub fn descriptor_indicator() -> ComponentDescriptor { + ComponentDescriptor { + archetype_name: Some("rerun.archetypes.SeriesLines".into()), + component_name: "rerun.components.SeriesLinesIndicator".into(), + archetype_field_name: None, + } + } +} + +static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 0usize]> = + once_cell::sync::Lazy::new(|| []); + +static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 1usize]> = + once_cell::sync::Lazy::new(|| [SeriesLines::descriptor_indicator()]); + +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 5usize]> = + once_cell::sync::Lazy::new(|| { + [ + SeriesLines::descriptor_colors(), + SeriesLines::descriptor_widths(), + SeriesLines::descriptor_names(), + SeriesLines::descriptor_visible_series(), + SeriesLines::descriptor_aggregation_policy(), + ] + }); + +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 6usize]> = + once_cell::sync::Lazy::new(|| { + [ + SeriesLines::descriptor_indicator(), + SeriesLines::descriptor_colors(), + SeriesLines::descriptor_widths(), + SeriesLines::descriptor_names(), + SeriesLines::descriptor_visible_series(), + SeriesLines::descriptor_aggregation_policy(), + ] + }); + +impl SeriesLines { + /// The total number of components in the archetype: 0 required, 1 recommended, 5 optional + pub const NUM_COMPONENTS: usize = 6usize; +} + +/// Indicator component for the [`SeriesLines`] [`::re_types_core::Archetype`] +pub type SeriesLinesIndicator = ::re_types_core::GenericIndicatorComponent; + +impl ::re_types_core::Archetype for SeriesLines { + type Indicator = SeriesLinesIndicator; + + #[inline] + fn name() -> ::re_types_core::ArchetypeName { + "rerun.archetypes.SeriesLines".into() + } + + #[inline] + fn display_name() -> &'static str { + "Series lines" + } + + #[inline] + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + SeriesLinesIndicator::DEFAULT.serialized().unwrap() + } + + #[inline] + fn required_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + REQUIRED_COMPONENTS.as_slice().into() + } + + #[inline] + fn recommended_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + RECOMMENDED_COMPONENTS.as_slice().into() + } + + #[inline] + fn optional_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + OPTIONAL_COMPONENTS.as_slice().into() + } + + #[inline] + fn all_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + ALL_COMPONENTS.as_slice().into() + } + + #[inline] + fn from_arrow_components( + arrow_data: impl IntoIterator, + ) -> DeserializationResult { + re_tracing::profile_function!(); + use ::re_types_core::{Loggable as _, ResultExt as _}; + let arrays_by_descr: ::nohash_hasher::IntMap<_, _> = arrow_data.into_iter().collect(); + let colors = arrays_by_descr + .get(&Self::descriptor_colors()) + .map(|array| SerializedComponentBatch::new(array.clone(), Self::descriptor_colors())); + let widths = arrays_by_descr + .get(&Self::descriptor_widths()) + .map(|array| SerializedComponentBatch::new(array.clone(), Self::descriptor_widths())); + let names = arrays_by_descr + .get(&Self::descriptor_names()) + .map(|array| SerializedComponentBatch::new(array.clone(), Self::descriptor_names())); + let visible_series = arrays_by_descr + .get(&Self::descriptor_visible_series()) + .map(|array| { + SerializedComponentBatch::new(array.clone(), Self::descriptor_visible_series()) + }); + let aggregation_policy = arrays_by_descr + .get(&Self::descriptor_aggregation_policy()) + .map(|array| { + SerializedComponentBatch::new(array.clone(), Self::descriptor_aggregation_policy()) + }); + Ok(Self { + colors, + widths, + names, + visible_series, + aggregation_policy, + }) + } +} + +impl ::re_types_core::AsComponents for SeriesLines { + #[inline] + fn as_serialized_batches(&self) -> Vec { + use ::re_types_core::Archetype as _; + [ + Some(Self::indicator()), + self.colors.clone(), + self.widths.clone(), + self.names.clone(), + self.visible_series.clone(), + self.aggregation_policy.clone(), + ] + .into_iter() + .flatten() + .collect() + } +} + +impl ::re_types_core::ArchetypeReflectionMarker for SeriesLines {} + +impl SeriesLines { + /// Create a new `SeriesLines`. + #[inline] + pub fn new() -> Self { + Self { + colors: None, + widths: None, + names: None, + visible_series: None, + aggregation_policy: None, + } + } + + /// Update only some specific fields of a `SeriesLines`. + #[inline] + pub fn update_fields() -> Self { + Self::default() + } + + /// Clear all the fields of a `SeriesLines`. + #[inline] + pub fn clear_fields() -> Self { + use ::re_types_core::Loggable as _; + Self { + colors: Some(SerializedComponentBatch::new( + crate::components::Color::arrow_empty(), + Self::descriptor_colors(), + )), + widths: Some(SerializedComponentBatch::new( + crate::components::StrokeWidth::arrow_empty(), + Self::descriptor_widths(), + )), + names: Some(SerializedComponentBatch::new( + crate::components::Name::arrow_empty(), + Self::descriptor_names(), + )), + visible_series: Some(SerializedComponentBatch::new( + crate::components::SeriesVisible::arrow_empty(), + Self::descriptor_visible_series(), + )), + aggregation_policy: Some(SerializedComponentBatch::new( + crate::components::AggregationPolicy::arrow_empty(), + Self::descriptor_aggregation_policy(), + )), + } + } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.colors + .map(|colors| colors.partitioned(_lengths.clone())) + .transpose()?, + self.widths + .map(|widths| widths.partitioned(_lengths.clone())) + .transpose()?, + self.names + .map(|names| names.partitioned(_lengths.clone())) + .transpose()?, + self.visible_series + .map(|visible_series| visible_series.partitioned(_lengths.clone())) + .transpose()?, + self.aggregation_policy + .map(|aggregation_policy| aggregation_policy.partitioned(_lengths.clone())) + .transpose()?, + ]; + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) + } + + /// Helper to partition the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling [`Self::columns`] with `std::iter::take(1).repeat(n)`, + /// where `n` is automatically guessed. + #[inline] + pub fn columns_of_unit_batches( + self, + ) -> SerializationResult> { + let len_colors = self.colors.as_ref().map(|b| b.array.len()); + let len_widths = self.widths.as_ref().map(|b| b.array.len()); + let len_names = self.names.as_ref().map(|b| b.array.len()); + let len_visible_series = self.visible_series.as_ref().map(|b| b.array.len()); + let len_aggregation_policy = self.aggregation_policy.as_ref().map(|b| b.array.len()); + let len = None + .or(len_colors) + .or(len_widths) + .or(len_names) + .or(len_visible_series) + .or(len_aggregation_policy) + .unwrap_or(0); + self.columns(std::iter::repeat(1).take(len)) + } + + /// Color for the corresponding series. + /// + /// May change over time, but can cause discontinuities in the line. + #[inline] + pub fn with_colors( + mut self, + colors: impl IntoIterator>, + ) -> Self { + self.colors = try_serialize_field(Self::descriptor_colors(), colors); + self + } + + /// Stroke width for the corresponding series. + /// + /// May change over time, but can cause discontinuities in the line. + #[inline] + pub fn with_widths( + mut self, + widths: impl IntoIterator>, + ) -> Self { + self.widths = try_serialize_field(Self::descriptor_widths(), widths); + self + } + + /// Display name of the series. + /// + /// Used in the legend. Expected to be unchanging over time. + #[inline] + pub fn with_names( + mut self, + names: impl IntoIterator>, + ) -> Self { + self.names = try_serialize_field(Self::descriptor_names(), names); + self + } + + /// Which lines are visible. + /// + /// If not set, all line series on this entity are visible. + /// Unlike with the regular visibility property of the entire entity, any series that is hidden + /// via this property will still be visible in the legend. + /// + /// May change over time, but can cause discontinuities in the line. + #[inline] + pub fn with_visible_series( + mut self, + visible_series: impl IntoIterator>, + ) -> Self { + self.visible_series = + try_serialize_field(Self::descriptor_visible_series(), visible_series); + self + } + + /// Configures the zoom-dependent scalar aggregation. + /// + /// This is done only if steps on the X axis go below a single pixel, + /// i.e. a single pixel covers more than one tick worth of data. It can greatly improve performance + /// (and readability) in such situations as it prevents overdraw. + /// + /// Expected to be unchanging over time. + #[inline] + pub fn with_aggregation_policy( + mut self, + aggregation_policy: impl Into, + ) -> Self { + self.aggregation_policy = + try_serialize_field(Self::descriptor_aggregation_policy(), [aggregation_policy]); + self + } + + /// This method makes it possible to pack multiple [`crate::components::AggregationPolicy`] in a single component batch. + /// + /// This only makes sense when used in conjunction with [`Self::columns`]. [`Self::with_aggregation_policy`] should + /// be used when logging a single row's worth of data. + #[inline] + pub fn with_many_aggregation_policy( + mut self, + aggregation_policy: impl IntoIterator>, + ) -> Self { + self.aggregation_policy = + try_serialize_field(Self::descriptor_aggregation_policy(), aggregation_policy); + self + } +} + +impl ::re_byte_size::SizeBytes for SeriesLines { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.colors.heap_size_bytes() + + self.widths.heap_size_bytes() + + self.names.heap_size_bytes() + + self.visible_series.heap_size_bytes() + + self.aggregation_policy.heap_size_bytes() + } +} diff --git a/crates/store/re_types/src/archetypes/series_point.rs b/crates/store/re_types/src/archetypes/series_point.rs index 1f7e9a91ff9a..793692e5bb90 100644 --- a/crates/store/re_types/src/archetypes/series_point.rs +++ b/crates/store/re_types/src/archetypes/series_point.rs @@ -11,6 +11,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_lines)] +#![expect(deprecated)] use ::re_types_core::try_serialize_field; use ::re_types_core::SerializationResult; @@ -22,7 +23,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// This archetype only provides styling information and should be logged as static /// when possible. The underlying data needs to be logged to the same entity-path using -/// [`archetypes::Scalar`][crate::archetypes::Scalar]. +/// [`archetypes::Scalars`][crate::archetypes::Scalars]. /// /// ## Example /// @@ -36,27 +37,27 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// // Log two point series under a shared root so that they show in the same plot by default. /// rec.log_static( /// "trig/sin", -/// &rerun::SeriesPoint::new() -/// .with_color([255, 0, 0]) -/// .with_name("sin(0.01t)") -/// .with_marker(rerun::components::MarkerShape::Circle) -/// .with_marker_size(4.0), +/// &rerun::SeriesPoints::new() +/// .with_colors([[255, 0, 0]]) +/// .with_names(["sin(0.01t)"]) +/// .with_markers([rerun::components::MarkerShape::Circle]) +/// .with_marker_sizes([4.0]), /// )?; /// rec.log_static( /// "trig/cos", -/// &rerun::SeriesPoint::new() -/// .with_color([0, 255, 0]) -/// .with_name("cos(0.01t)") -/// .with_marker(rerun::components::MarkerShape::Cross) -/// .with_marker_size(2.0), +/// &rerun::SeriesPoints::new() +/// .with_colors([[0, 255, 0]]) +/// .with_names(["cos(0.01t)"]) +/// .with_markers([rerun::components::MarkerShape::Cross]) +/// .with_marker_sizes([2.0]), /// )?; /// /// for t in 0..((std::f32::consts::TAU * 2.0 * 10.0) as i64) { /// rec.set_time_sequence("step", t); /// /// // Log two time series under a shared root so that they show in the same plot by default. -/// rec.log("trig/sin", &rerun::Scalar::new((t as f64 / 10.0).sin()))?; -/// rec.log("trig/cos", &rerun::Scalar::new((t as f64 / 10.0).cos()))?; +/// rec.log("trig/sin", &rerun::Scalars::one((t as f64 / 10.0).sin()))?; +/// rec.log("trig/cos", &rerun::Scalars::one((t as f64 / 10.0).cos()))?; /// } /// /// Ok(()) @@ -72,6 +73,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// #[derive(Clone, Debug, Default)] +#[deprecated(note = "Use `SeriesPoints` instead.")] pub struct SeriesPoint { /// Color for the corresponding series. pub color: Option, diff --git a/crates/store/re_types/src/archetypes/series_points.rs b/crates/store/re_types/src/archetypes/series_points.rs new file mode 100644 index 000000000000..3f8e3d790368 --- /dev/null +++ b/crates/store/re_types/src/archetypes/series_points.rs @@ -0,0 +1,491 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/store/re_types/definitions/rerun/archetypes/series_points.fbs". + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::map_flatten)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] + +use ::re_types_core::try_serialize_field; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch as _, SerializedComponentBatch}; +use ::re_types_core::{ComponentDescriptor, ComponentName}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Archetype**: Define the style properties for one or more point series (scatter plot) in a chart. +/// +/// This archetype only provides styling information. +/// Changes over time are supported for most but not all its fields (see respective fields for details), +/// it's generally recommended to log this type as static. +/// +/// The underlying data needs to be logged to the same entity-path using [`archetypes::Scalars`][crate::archetypes::Scalars]. +/// Dimensionality of the scalar arrays logged at each time point is assumed to be the same over time. +/// +/// ## Example +/// +/// ### Point series +/// ```ignore +/// fn main() -> Result<(), Box> { +/// let rec = rerun::RecordingStreamBuilder::new("rerun_example_series_point_style").spawn()?; +/// +/// // Set up plot styling: +/// // They are logged static as they don't change over time and apply to all timelines. +/// // Log two point series under a shared root so that they show in the same plot by default. +/// rec.log_static( +/// "trig/sin", +/// &rerun::SeriesPoints::new() +/// .with_colors([[255, 0, 0]]) +/// .with_names(["sin(0.01t)"]) +/// .with_markers([rerun::components::MarkerShape::Circle]) +/// .with_marker_sizes([4.0]), +/// )?; +/// rec.log_static( +/// "trig/cos", +/// &rerun::SeriesPoints::new() +/// .with_colors([[0, 255, 0]]) +/// .with_names(["cos(0.01t)"]) +/// .with_markers([rerun::components::MarkerShape::Cross]) +/// .with_marker_sizes([2.0]), +/// )?; +/// +/// for t in 0..((std::f32::consts::TAU * 2.0 * 10.0) as i64) { +/// rec.set_time_sequence("step", t); +/// +/// // Log two time series under a shared root so that they show in the same plot by default. +/// rec.log("trig/sin", &rerun::Scalars::one((t as f64 / 10.0).sin()))?; +/// rec.log("trig/cos", &rerun::Scalars::one((t as f64 / 10.0).cos()))?; +/// } +/// +/// Ok(()) +/// } +/// ``` +///
+/// +/// +/// +/// +/// +/// +/// +///
+#[derive(Clone, Debug, Default)] +pub struct SeriesPoints { + /// Color for the corresponding series. + /// + /// May change over time, but can cause discontinuities in the line. + pub colors: Option, + + /// What shape to use to represent the point + /// + /// May change over time. + pub markers: Option, + + /// Display name of the series. + /// + /// Used in the legend. Expected to be unchanging over time. + pub names: Option, + + /// Which lines are visible. + /// + /// If not set, all line series on this entity are visible. + /// Unlike with the regular visibility property of the entire entity, any series that is hidden + /// via this property will still be visible in the legend. + /// + /// May change over time. + pub visible_series: Option, + + /// Sizes of the markers. + /// + /// May change over time. + pub marker_sizes: Option, +} + +impl SeriesPoints { + /// Returns the [`ComponentDescriptor`] for [`Self::colors`]. + #[inline] + pub fn descriptor_colors() -> ComponentDescriptor { + ComponentDescriptor { + archetype_name: Some("rerun.archetypes.SeriesPoints".into()), + component_name: "rerun.components.Color".into(), + archetype_field_name: Some("colors".into()), + } + } + + /// Returns the [`ComponentDescriptor`] for [`Self::markers`]. + #[inline] + pub fn descriptor_markers() -> ComponentDescriptor { + ComponentDescriptor { + archetype_name: Some("rerun.archetypes.SeriesPoints".into()), + component_name: "rerun.components.MarkerShape".into(), + archetype_field_name: Some("markers".into()), + } + } + + /// Returns the [`ComponentDescriptor`] for [`Self::names`]. + #[inline] + pub fn descriptor_names() -> ComponentDescriptor { + ComponentDescriptor { + archetype_name: Some("rerun.archetypes.SeriesPoints".into()), + component_name: "rerun.components.Name".into(), + archetype_field_name: Some("names".into()), + } + } + + /// Returns the [`ComponentDescriptor`] for [`Self::visible_series`]. + #[inline] + pub fn descriptor_visible_series() -> ComponentDescriptor { + ComponentDescriptor { + archetype_name: Some("rerun.archetypes.SeriesPoints".into()), + component_name: "rerun.components.SeriesVisible".into(), + archetype_field_name: Some("visible_series".into()), + } + } + + /// Returns the [`ComponentDescriptor`] for [`Self::marker_sizes`]. + #[inline] + pub fn descriptor_marker_sizes() -> ComponentDescriptor { + ComponentDescriptor { + archetype_name: Some("rerun.archetypes.SeriesPoints".into()), + component_name: "rerun.components.MarkerSize".into(), + archetype_field_name: Some("marker_sizes".into()), + } + } + + /// Returns the [`ComponentDescriptor`] for the associated indicator component. + #[inline] + pub fn descriptor_indicator() -> ComponentDescriptor { + ComponentDescriptor { + archetype_name: Some("rerun.archetypes.SeriesPoints".into()), + component_name: "rerun.components.SeriesPointsIndicator".into(), + archetype_field_name: None, + } + } +} + +static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 0usize]> = + once_cell::sync::Lazy::new(|| []); + +static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 1usize]> = + once_cell::sync::Lazy::new(|| [SeriesPoints::descriptor_indicator()]); + +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 5usize]> = + once_cell::sync::Lazy::new(|| { + [ + SeriesPoints::descriptor_colors(), + SeriesPoints::descriptor_markers(), + SeriesPoints::descriptor_names(), + SeriesPoints::descriptor_visible_series(), + SeriesPoints::descriptor_marker_sizes(), + ] + }); + +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 6usize]> = + once_cell::sync::Lazy::new(|| { + [ + SeriesPoints::descriptor_indicator(), + SeriesPoints::descriptor_colors(), + SeriesPoints::descriptor_markers(), + SeriesPoints::descriptor_names(), + SeriesPoints::descriptor_visible_series(), + SeriesPoints::descriptor_marker_sizes(), + ] + }); + +impl SeriesPoints { + /// The total number of components in the archetype: 0 required, 1 recommended, 5 optional + pub const NUM_COMPONENTS: usize = 6usize; +} + +/// Indicator component for the [`SeriesPoints`] [`::re_types_core::Archetype`] +pub type SeriesPointsIndicator = ::re_types_core::GenericIndicatorComponent; + +impl ::re_types_core::Archetype for SeriesPoints { + type Indicator = SeriesPointsIndicator; + + #[inline] + fn name() -> ::re_types_core::ArchetypeName { + "rerun.archetypes.SeriesPoints".into() + } + + #[inline] + fn display_name() -> &'static str { + "Series points" + } + + #[inline] + fn indicator() -> SerializedComponentBatch { + #[allow(clippy::unwrap_used)] + SeriesPointsIndicator::DEFAULT.serialized().unwrap() + } + + #[inline] + fn required_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + REQUIRED_COMPONENTS.as_slice().into() + } + + #[inline] + fn recommended_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + RECOMMENDED_COMPONENTS.as_slice().into() + } + + #[inline] + fn optional_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + OPTIONAL_COMPONENTS.as_slice().into() + } + + #[inline] + fn all_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + ALL_COMPONENTS.as_slice().into() + } + + #[inline] + fn from_arrow_components( + arrow_data: impl IntoIterator, + ) -> DeserializationResult { + re_tracing::profile_function!(); + use ::re_types_core::{Loggable as _, ResultExt as _}; + let arrays_by_descr: ::nohash_hasher::IntMap<_, _> = arrow_data.into_iter().collect(); + let colors = arrays_by_descr + .get(&Self::descriptor_colors()) + .map(|array| SerializedComponentBatch::new(array.clone(), Self::descriptor_colors())); + let markers = arrays_by_descr + .get(&Self::descriptor_markers()) + .map(|array| SerializedComponentBatch::new(array.clone(), Self::descriptor_markers())); + let names = arrays_by_descr + .get(&Self::descriptor_names()) + .map(|array| SerializedComponentBatch::new(array.clone(), Self::descriptor_names())); + let visible_series = arrays_by_descr + .get(&Self::descriptor_visible_series()) + .map(|array| { + SerializedComponentBatch::new(array.clone(), Self::descriptor_visible_series()) + }); + let marker_sizes = arrays_by_descr + .get(&Self::descriptor_marker_sizes()) + .map(|array| { + SerializedComponentBatch::new(array.clone(), Self::descriptor_marker_sizes()) + }); + Ok(Self { + colors, + markers, + names, + visible_series, + marker_sizes, + }) + } +} + +impl ::re_types_core::AsComponents for SeriesPoints { + #[inline] + fn as_serialized_batches(&self) -> Vec { + use ::re_types_core::Archetype as _; + [ + Some(Self::indicator()), + self.colors.clone(), + self.markers.clone(), + self.names.clone(), + self.visible_series.clone(), + self.marker_sizes.clone(), + ] + .into_iter() + .flatten() + .collect() + } +} + +impl ::re_types_core::ArchetypeReflectionMarker for SeriesPoints {} + +impl SeriesPoints { + /// Create a new `SeriesPoints`. + #[inline] + pub fn new() -> Self { + Self { + colors: None, + markers: None, + names: None, + visible_series: None, + marker_sizes: None, + } + } + + /// Update only some specific fields of a `SeriesPoints`. + #[inline] + pub fn update_fields() -> Self { + Self::default() + } + + /// Clear all the fields of a `SeriesPoints`. + #[inline] + pub fn clear_fields() -> Self { + use ::re_types_core::Loggable as _; + Self { + colors: Some(SerializedComponentBatch::new( + crate::components::Color::arrow_empty(), + Self::descriptor_colors(), + )), + markers: Some(SerializedComponentBatch::new( + crate::components::MarkerShape::arrow_empty(), + Self::descriptor_markers(), + )), + names: Some(SerializedComponentBatch::new( + crate::components::Name::arrow_empty(), + Self::descriptor_names(), + )), + visible_series: Some(SerializedComponentBatch::new( + crate::components::SeriesVisible::arrow_empty(), + Self::descriptor_visible_series(), + )), + marker_sizes: Some(SerializedComponentBatch::new( + crate::components::MarkerSize::arrow_empty(), + Self::descriptor_marker_sizes(), + )), + } + } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s + /// instead, via [`SerializedComponentBatch::partitioned`]. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + /// + /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn] + #[inline] + pub fn columns( + self, + _lengths: I, + ) -> SerializationResult> + where + I: IntoIterator + Clone, + { + let columns = [ + self.colors + .map(|colors| colors.partitioned(_lengths.clone())) + .transpose()?, + self.markers + .map(|markers| markers.partitioned(_lengths.clone())) + .transpose()?, + self.names + .map(|names| names.partitioned(_lengths.clone())) + .transpose()?, + self.visible_series + .map(|visible_series| visible_series.partitioned(_lengths.clone())) + .transpose()?, + self.marker_sizes + .map(|marker_sizes| marker_sizes.partitioned(_lengths.clone())) + .transpose()?, + ]; + Ok(columns + .into_iter() + .flatten() + .chain([::re_types_core::indicator_column::( + _lengths.into_iter().count(), + )?])) + } + + /// Helper to partition the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling [`Self::columns`] with `std::iter::take(1).repeat(n)`, + /// where `n` is automatically guessed. + #[inline] + pub fn columns_of_unit_batches( + self, + ) -> SerializationResult> { + let len_colors = self.colors.as_ref().map(|b| b.array.len()); + let len_markers = self.markers.as_ref().map(|b| b.array.len()); + let len_names = self.names.as_ref().map(|b| b.array.len()); + let len_visible_series = self.visible_series.as_ref().map(|b| b.array.len()); + let len_marker_sizes = self.marker_sizes.as_ref().map(|b| b.array.len()); + let len = None + .or(len_colors) + .or(len_markers) + .or(len_names) + .or(len_visible_series) + .or(len_marker_sizes) + .unwrap_or(0); + self.columns(std::iter::repeat(1).take(len)) + } + + /// Color for the corresponding series. + /// + /// May change over time, but can cause discontinuities in the line. + #[inline] + pub fn with_colors( + mut self, + colors: impl IntoIterator>, + ) -> Self { + self.colors = try_serialize_field(Self::descriptor_colors(), colors); + self + } + + /// What shape to use to represent the point + /// + /// May change over time. + #[inline] + pub fn with_markers( + mut self, + markers: impl IntoIterator>, + ) -> Self { + self.markers = try_serialize_field(Self::descriptor_markers(), markers); + self + } + + /// Display name of the series. + /// + /// Used in the legend. Expected to be unchanging over time. + #[inline] + pub fn with_names( + mut self, + names: impl IntoIterator>, + ) -> Self { + self.names = try_serialize_field(Self::descriptor_names(), names); + self + } + + /// Which lines are visible. + /// + /// If not set, all line series on this entity are visible. + /// Unlike with the regular visibility property of the entire entity, any series that is hidden + /// via this property will still be visible in the legend. + /// + /// May change over time. + #[inline] + pub fn with_visible_series( + mut self, + visible_series: impl IntoIterator>, + ) -> Self { + self.visible_series = + try_serialize_field(Self::descriptor_visible_series(), visible_series); + self + } + + /// Sizes of the markers. + /// + /// May change over time. + #[inline] + pub fn with_marker_sizes( + mut self, + marker_sizes: impl IntoIterator>, + ) -> Self { + self.marker_sizes = try_serialize_field(Self::descriptor_marker_sizes(), marker_sizes); + self + } +} + +impl ::re_byte_size::SizeBytes for SeriesPoints { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.colors.heap_size_bytes() + + self.markers.heap_size_bytes() + + self.names.heap_size_bytes() + + self.visible_series.heap_size_bytes() + + self.marker_sizes.heap_size_bytes() + } +} diff --git a/crates/store/re_types/src/blueprint/views/time_series_view.rs b/crates/store/re_types/src/blueprint/views/time_series_view.rs index 1a02f4fa3f57..25beee423403 100644 --- a/crates/store/re_types/src/blueprint/views/time_series_view.rs +++ b/crates/store/re_types/src/blueprint/views/time_series_view.rs @@ -18,7 +18,7 @@ use ::re_types_core::{ComponentBatch as _, SerializedComponentBatch}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; -/// **View**: A time series view for scalars over time, for use with [`archetypes::Scalar`][crate::archetypes::Scalar]. +/// **View**: A time series view for scalars over time, for use with [`archetypes::Scalars`][crate::archetypes::Scalars]. #[derive(Clone, Debug)] pub struct TimeSeriesView { /// Configures the vertical axis of the plot. diff --git a/crates/store/re_types/src/reflection/mod.rs b/crates/store/re_types/src/reflection/mod.rs index 7d57bd2983b4..dd4be5aa7c44 100644 --- a/crates/store/re_types/src/reflection/mod.rs +++ b/crates/store/re_types/src/reflection/mod.rs @@ -1979,7 +1979,7 @@ fn generate_archetype_reflection() -> ArchetypeReflectionMap { ArchetypeName::new("rerun.archetypes.Scalar"), ArchetypeReflection { display_name: "Scalar", - deprecation_notice: None, + deprecation_notice: Some("Use `Scalars` instead."), scope: None, view_types: &["TimeSeriesView"], fields: vec![ @@ -1989,6 +1989,20 @@ fn generate_archetype_reflection() -> ArchetypeReflectionMap { ], }, ), + ( + ArchetypeName::new("rerun.archetypes.Scalars"), + ArchetypeReflection { + display_name: "Scalars", + deprecation_notice: None, + scope: None, + view_types: &["TimeSeriesView"], + fields: vec![ + ArchetypeFieldReflection { name : "scalars", display_name : + "Scalars", component_name : "rerun.components.Scalar".into(), + docstring_md : "The scalar values to log.", is_required : true, }, + ], + }, + ), ( ArchetypeName::new("rerun.archetypes.SegmentationImage"), ArchetypeReflection { @@ -2019,7 +2033,7 @@ fn generate_archetype_reflection() -> ArchetypeReflectionMap { ArchetypeName::new("rerun.archetypes.SeriesLine"), ArchetypeReflection { display_name: "Series line", - deprecation_notice: None, + deprecation_notice: Some("Use `SeriesLines` instead."), scope: None, view_types: &["TimeSeriesView"], fields: vec![ @@ -2045,11 +2059,43 @@ fn generate_archetype_reflection() -> ArchetypeReflectionMap { ], }, ), + ( + ArchetypeName::new("rerun.archetypes.SeriesLines"), + ArchetypeReflection { + display_name: "Series lines", + deprecation_notice: None, + scope: None, + view_types: &["TimeSeriesView"], + fields: vec![ + ArchetypeFieldReflection { name : "colors", display_name : "Colors", + component_name : "rerun.components.Color".into(), docstring_md : + "Color for the corresponding series.\n\nMay change over time, but can cause discontinuities in the line.", + is_required : false, }, ArchetypeFieldReflection { name : "widths", + display_name : "Widths", component_name : + "rerun.components.StrokeWidth".into(), docstring_md : + "Stroke width for the corresponding series.\n\nMay change over time, but can cause discontinuities in the line.", + is_required : false, }, ArchetypeFieldReflection { name : "names", + display_name : "Names", component_name : "rerun.components.Name" + .into(), docstring_md : + "Display name of the series.\n\nUsed in the legend. Expected to be unchanging over time.", + is_required : false, }, ArchetypeFieldReflection { name : + "visible_series", display_name : "Visible series", component_name : + "rerun.components.SeriesVisible".into(), docstring_md : + "Which lines are visible.\n\nIf not set, all line series on this entity are visible.\nUnlike with the regular visibility property of the entire entity, any series that is hidden\nvia this property will still be visible in the legend.\n\nMay change over time, but can cause discontinuities in the line.", + is_required : false, }, ArchetypeFieldReflection { name : + "aggregation_policy", display_name : "Aggregation policy", + component_name : "rerun.components.AggregationPolicy".into(), + docstring_md : + "Configures the zoom-dependent scalar aggregation.\n\nThis is done only if steps on the X axis go below a single pixel,\ni.e. a single pixel covers more than one tick worth of data. It can greatly improve performance\n(and readability) in such situations as it prevents overdraw.\n\nExpected to be unchanging over time.", + is_required : false, }, + ], + }, + ), ( ArchetypeName::new("rerun.archetypes.SeriesPoint"), ArchetypeReflection { display_name: "Series point", - deprecation_notice: None, + deprecation_notice: Some("Use `SeriesPoints` instead."), scope: None, view_types: &["TimeSeriesView"], fields: vec![ @@ -2073,6 +2119,37 @@ fn generate_archetype_reflection() -> ArchetypeReflectionMap { ], }, ), + ( + ArchetypeName::new("rerun.archetypes.SeriesPoints"), + ArchetypeReflection { + display_name: "Series points", + deprecation_notice: None, + scope: None, + view_types: &["TimeSeriesView"], + fields: vec![ + ArchetypeFieldReflection { name : "colors", display_name : "Colors", + component_name : "rerun.components.Color".into(), docstring_md : + "Color for the corresponding series.\n\nMay change over time, but can cause discontinuities in the line.", + is_required : false, }, ArchetypeFieldReflection { name : "markers", + display_name : "Markers", component_name : + "rerun.components.MarkerShape".into(), docstring_md : + "What shape to use to represent the point\n\nMay change over time.", + is_required : false, }, ArchetypeFieldReflection { name : "names", + display_name : "Names", component_name : "rerun.components.Name" + .into(), docstring_md : + "Display name of the series.\n\nUsed in the legend. Expected to be unchanging over time.", + is_required : false, }, ArchetypeFieldReflection { name : + "visible_series", display_name : "Visible series", component_name : + "rerun.components.SeriesVisible".into(), docstring_md : + "Which lines are visible.\n\nIf not set, all line series on this entity are visible.\nUnlike with the regular visibility property of the entire entity, any series that is hidden\nvia this property will still be visible in the legend.\n\nMay change over time.", + is_required : false, }, ArchetypeFieldReflection { name : + "marker_sizes", display_name : "Marker sizes", component_name : + "rerun.components.MarkerSize".into(), docstring_md : + "Sizes of the markers.\n\nMay change over time.", is_required : + false, }, + ], + }, + ), ( ArchetypeName::new("rerun.archetypes.Tensor"), ArchetypeReflection { diff --git a/crates/viewer/re_view_dataframe/tests/basic.rs b/crates/viewer/re_view_dataframe/tests/basic.rs index 1c8f0b1bf557..160bf662afc5 100644 --- a/crates/viewer/re_view_dataframe/tests/basic.rs +++ b/crates/viewer/re_view_dataframe/tests/basic.rs @@ -2,7 +2,7 @@ use re_chunk_store::RowId; use re_log_types::{Timeline, TimelineName}; -use re_types::archetypes::Scalar; +use re_types::archetypes::Scalars; use re_ui::UiExt as _; use re_view_dataframe::DataframeView; use re_viewer_context::test_context::TestContext; @@ -18,14 +18,14 @@ pub fn test_null_timeline() { let timeline_b = Timeline::new_sequence("timeline_b"); test_context.log_entity("first".into(), |builder| { - builder.with_archetype(RowId::new(), [(timeline_a, 0)], &Scalar::new(10.0)) + builder.with_archetype(RowId::new(), [(timeline_a, 0)], &Scalars::one(10.0)) }); test_context.log_entity("second".into(), |builder| { builder.with_archetype( RowId::new(), [(timeline_a, 1), (timeline_b, 10)], - &Scalar::new(12.0), + &Scalars::one(12.0), ) }); @@ -46,9 +46,9 @@ pub fn test_unknown_timeline() { test_context.log_entity("some_entity".into(), |builder| { builder - .with_archetype(RowId::new(), [(timeline, 0)], &Scalar::new(10.0)) - .with_archetype(RowId::new(), [(timeline, 1)], &Scalar::new(20.0)) - .with_archetype(RowId::new(), [(timeline, 2)], &Scalar::new(30.0)) + .with_archetype(RowId::new(), [(timeline, 0)], &Scalars::one(10.0)) + .with_archetype(RowId::new(), [(timeline, 1)], &Scalars::one(20.0)) + .with_archetype(RowId::new(), [(timeline, 2)], &Scalars::one(30.0)) }); let view_id = setup_blueprint(&mut test_context, &TimelineName::from("unknown_timeline")); diff --git a/crates/viewer/re_view_time_series/src/line_visualizer_system.rs b/crates/viewer/re_view_time_series/src/line_visualizer_system.rs index a50dd2c952a7..3bb07d46a5ea 100644 --- a/crates/viewer/re_view_time_series/src/line_visualizer_system.rs +++ b/crates/viewer/re_view_time_series/src/line_visualizer_system.rs @@ -5,7 +5,6 @@ use re_log_types::{EntityPath, TimeInt}; use re_types::archetypes; use re_types::components::{AggregationPolicy, ClearIsRecursive, SeriesVisible}; use re_types::{ - archetypes::SeriesLine, components::{Color, Name, Scalar, StrokeWidth}, Archetype as _, Component as _, }; @@ -25,7 +24,7 @@ use crate::util::{determine_time_per_pixel, determine_time_range, points_to_seri use crate::view_class::TimeSeriesViewState; use crate::{PlotPoint, PlotPointAttrs, PlotSeries, PlotSeriesKind}; -/// The system for rendering [`SeriesLine`] archetypes. +/// The system for rendering [`archetypes::SeriesLines`] archetypes. #[derive(Default, Debug)] pub struct SeriesLineSystem { pub all_series: Vec, @@ -33,7 +32,7 @@ pub struct SeriesLineSystem { impl IdentifiedViewSystem for SeriesLineSystem { fn identifier() -> re_viewer_context::ViewSystemIdentifier { - "SeriesLine".into() + "SeriesLines".into() } } @@ -41,15 +40,15 @@ const DEFAULT_STROKE_WIDTH: f32 = 0.75; impl VisualizerSystem for SeriesLineSystem { fn visualizer_query_info(&self) -> VisualizerQueryInfo { - let mut query_info = VisualizerQueryInfo::from_archetype::(); + let mut query_info = VisualizerQueryInfo::from_archetype::(); query_info.queried.extend( - SeriesLine::all_components() + archetypes::SeriesLines::all_components() .iter() .map(|descr| descr.component_name), ); query_info.indicators = - std::iter::once(SeriesLine::descriptor_indicator().component_name).collect(); + [archetypes::SeriesLines::descriptor_indicator().component_name].into(); query_info } diff --git a/crates/viewer/re_view_time_series/src/point_visualizer_system.rs b/crates/viewer/re_view_time_series/src/point_visualizer_system.rs index e54b1c47530f..99bf3e0d6fa9 100644 --- a/crates/viewer/re_view_time_series/src/point_visualizer_system.rs +++ b/crates/viewer/re_view_time_series/src/point_visualizer_system.rs @@ -1,7 +1,7 @@ use itertools::Itertools as _; use re_types::{ - archetypes::{self, SeriesPoint}, + archetypes, components::{Color, MarkerShape, MarkerSize, Name, Scalar, SeriesVisible}, Archetype as _, Component as _, }; @@ -22,7 +22,7 @@ use crate::{ PlotPoint, PlotPointAttrs, PlotSeries, PlotSeriesKind, ScatterAttrs, }; -/// The system for rendering [`SeriesPoint`] archetypes. +/// The system for rendering [`archetypes::SeriesPoints`] archetypes. #[derive(Default, Debug)] pub struct SeriesPointSystem { pub all_series: Vec, @@ -30,7 +30,7 @@ pub struct SeriesPointSystem { impl IdentifiedViewSystem for SeriesPointSystem { fn identifier() -> re_viewer_context::ViewSystemIdentifier { - "SeriesPoint".into() + "SeriesPoints".into() } } @@ -40,15 +40,15 @@ const DEFAULT_MARKER_SIZE: f32 = 3.0; impl VisualizerSystem for SeriesPointSystem { fn visualizer_query_info(&self) -> VisualizerQueryInfo { - let mut query_info = VisualizerQueryInfo::from_archetype::(); + let mut query_info = VisualizerQueryInfo::from_archetype::(); query_info.queried.extend( - SeriesPoint::all_components() + archetypes::SeriesPoints::all_components() .iter() .map(|descr| descr.component_name), ); query_info.indicators = - std::iter::once(SeriesPoint::descriptor_indicator().component_name).collect(); + [archetypes::SeriesPoints::descriptor_indicator().component_name].into(); query_info } diff --git a/crates/viewer/re_view_time_series/src/view_class.rs b/crates/viewer/re_view_time_series/src/view_class.rs index 306a3aa29b4a..5413325cff22 100644 --- a/crates/viewer/re_view_time_series/src/view_class.rs +++ b/crates/viewer/re_view_time_series/src/view_class.rs @@ -6,7 +6,7 @@ use re_chunk_store::TimeType; use re_format::next_grid_tick_magnitude_ns; use re_log_types::{EntityPath, ResolvedEntityPathFilter, TimeInt}; use re_types::{ - archetypes::{SeriesLine, SeriesPoint}, + archetypes::{SeriesLines, SeriesPoints}, blueprint::{ archetypes::{PlotLegend, ScalarAxis}, components::{Corner2D, LockRangeDuringZoom}, @@ -679,8 +679,8 @@ fn update_series_visibility_overrides_from_plot( let override_path = result.override_path(); let descriptor = match series.kind { - PlotSeriesKind::Continuous => Some(SeriesLine::descriptor_visible_series()), - PlotSeriesKind::Scatter(_) => Some(SeriesPoint::descriptor_visible_series()), + PlotSeriesKind::Continuous => Some(SeriesLines::descriptor_visible_series()), + PlotSeriesKind::Scatter(_) => Some(SeriesPoints::descriptor_visible_series()), PlotSeriesKind::Clear => { if cfg!(debug_assertions) { unreachable!( diff --git a/crates/viewer/re_view_time_series/tests/basic.rs b/crates/viewer/re_view_time_series/tests/basic.rs index 257f5d0107a9..4acbbcae9e15 100644 --- a/crates/viewer/re_view_time_series/tests/basic.rs +++ b/crates/viewer/re_view_time_series/tests/basic.rs @@ -29,14 +29,14 @@ fn test_clear_series_points_and_line_impl(two_series_per_entity: bool) { builder.with_archetype( RowId::new(), TimePoint::default(), - &re_types::archetypes::SeriesLine::new(), + &re_types::archetypes::SeriesLines::new(), ) }); test_context.log_entity("plots/point".into(), |builder| { builder.with_archetype( RowId::new(), TimePoint::default(), - &re_types::archetypes::SeriesPoint::new(), + &re_types::archetypes::SeriesPoints::new(), ) }); @@ -58,12 +58,12 @@ fn test_clear_series_points_and_line_impl(two_series_per_entity: bool) { } _ => { let data = if two_series_per_entity { - re_types::archetypes::Scalar::default().with_many_scalar([ + re_types::archetypes::Scalars::default().with_scalars([ (i as f64 / 5.0).sin(), (i as f64 / 5.0 + 1.0).cos(), // Shifted a bit to make the cap more visible ]) } else { - re_types::archetypes::Scalar::new((i as f64 / 5.0).sin()) + re_types::archetypes::Scalars::one((i as f64 / 5.0).sin()) }; test_context.log_entity("plots/line".into(), |builder| { @@ -96,20 +96,22 @@ fn test_clear_series_points_and_line_impl(two_series_per_entity: bool) { fn scalars_for_properties_test( step: i64, multiple_scalars: bool, -) -> (re_types::archetypes::Scalar, re_types::archetypes::Scalar) { +) -> (re_types::archetypes::Scalars, re_types::archetypes::Scalars) { if multiple_scalars { ( - re_types::archetypes::Scalar::default().with_many_scalar([ + re_types::archetypes::Scalars::new([ (step as f64 / 5.0).sin() + 1.0, (step as f64 / 5.0).cos() + 1.0, ]), - re_types::archetypes::Scalar::default() - .with_many_scalar([(step as f64 / 5.0).cos(), (step as f64 / 5.0).sin()]), + re_types::archetypes::Scalars::new([ + (step as f64 / 5.0).cos(), + (step as f64 / 5.0).sin(), + ]), ) } else { ( - re_types::archetypes::Scalar::new((step as f64 / 5.0).sin()), - re_types::archetypes::Scalar::new((step as f64 / 5.0).cos()), + re_types::archetypes::Scalars::one((step as f64 / 5.0).sin()), + re_types::archetypes::Scalars::one((step as f64 / 5.0).cos()), ) } } @@ -126,18 +128,18 @@ fn test_line_properties_impl(multiple_properties: bool, multiple_scalars: bool) let mut test_context = get_test_context(); let properties_static = if multiple_properties { - re_types::archetypes::SeriesLine::new() - .with_many_width([4.0, 8.0]) - .with_many_color([ + re_types::archetypes::SeriesLines::new() + .with_widths([4.0, 8.0]) + .with_colors([ re_types::components::Color::from_rgb(255, 0, 255), re_types::components::Color::from_rgb(0, 255, 0), ]) - .with_many_name(["static_0", "static_1"]) + .with_names(["static_0", "static_1"]) } else { - re_types::archetypes::SeriesLine::new() - .with_width(4.0) - .with_color(re_types::components::Color::from_rgb(255, 0, 255)) - .with_name("static") + re_types::archetypes::SeriesLines::new() + .with_widths([4.0]) + .with_colors([re_types::components::Color::from_rgb(255, 0, 255)]) + .with_names(["static"]) }; test_context.log_entity("entity_static_props".into(), |builder| { builder.with_archetype(RowId::new(), TimePoint::default(), &properties_static) @@ -147,16 +149,16 @@ fn test_line_properties_impl(multiple_properties: bool, multiple_scalars: bool) let timepoint = TimePoint::from([(test_context.active_timeline(), step)]); let properties = if multiple_properties { - re_types::archetypes::SeriesLine::new() - .with_many_color([color_gradient0(step), color_gradient1(step)]) - .with_many_width([(32.0 - step as f32) * 0.5, step as f32 * 0.5]) + re_types::archetypes::SeriesLines::new() + .with_colors([color_gradient0(step), color_gradient1(step)]) + .with_widths([(32.0 - step as f32) * 0.5, step as f32 * 0.5]) // Only the first set of name will be shown, but should be handled gracefully. - .with_many_name([format!("dynamic_{step}_0"), format!("dynamic_{step}_1")]) + .with_names([format!("dynamic_{step}_0"), format!("dynamic_{step}_1")]) } else { - re_types::archetypes::SeriesLine::new() - .with_color(color_gradient0(step)) - .with_width((32.0 - step as f32) * 0.5) - .with_name(format!("dynamic_{step}")) + re_types::archetypes::SeriesLines::new() + .with_colors([color_gradient0(step)]) + .with_widths([(32.0 - step as f32) * 0.5]) + .with_names([format!("dynamic_{step}")]) }; let (scalars_static, scalars_dynamic) = scalars_for_properties_test(step, multiple_scalars); @@ -212,23 +214,23 @@ fn test_point_properties_impl(multiple_properties: bool, multiple_scalars: bool) let mut test_context = get_test_context(); let static_props = if multiple_properties { - re_types::archetypes::SeriesPoint::new() - .with_many_marker_size([4.0, 8.0]) - .with_many_marker([ + re_types::archetypes::SeriesPoints::new() + .with_marker_sizes([4.0, 8.0]) + .with_markers([ re_types::components::MarkerShape::Cross, re_types::components::MarkerShape::Plus, ]) - .with_many_color([ + .with_colors([ re_types::components::Color::from_rgb(255, 0, 255), re_types::components::Color::from_rgb(0, 255, 0), ]) - .with_many_name(["static_0", "static_1"]) + .with_names(["static_0", "static_1"]) } else { - re_types::archetypes::SeriesPoint::new() - .with_marker_size(4.0) - .with_marker(re_types::components::MarkerShape::Cross) - .with_color(re_types::components::Color::from_rgb(255, 0, 255)) - .with_name("static") + re_types::archetypes::SeriesPoints::new() + .with_marker_sizes([4.0]) + .with_markers([re_types::components::MarkerShape::Cross]) + .with_colors([re_types::components::Color::from_rgb(255, 0, 255)]) + .with_names(["static"]) }; test_context.log_entity("entity_static_props".into(), |builder| { @@ -239,20 +241,20 @@ fn test_point_properties_impl(multiple_properties: bool, multiple_scalars: bool) let timepoint = TimePoint::from([(test_context.active_timeline(), step)]); let properties = if multiple_properties { - re_types::archetypes::SeriesPoint::new() - .with_many_color([color_gradient0(step), color_gradient1(step)]) - .with_many_marker_size([(32.0 - step as f32) * 0.5, step as f32 * 0.5]) - .with_many_marker([ + re_types::archetypes::SeriesPoints::new() + .with_colors([color_gradient0(step), color_gradient1(step)]) + .with_marker_sizes([(32.0 - step as f32) * 0.5, step as f32 * 0.5]) + .with_markers([ MARKER_LIST[step as usize % MARKER_LIST.len()], MARKER_LIST[(step + 1) as usize % MARKER_LIST.len()], ]) - .with_many_name([format!("dynamic_{step}_0"), format!("dynamic_{step}_1")]) + .with_names([format!("dynamic_{step}_0"), format!("dynamic_{step}_1")]) } else { - re_types::archetypes::SeriesPoint::new() - .with_color(color_gradient0(step)) - .with_marker_size((32.0 - step as f32) * 0.5) - .with_marker(MARKER_LIST[step as usize % MARKER_LIST.len()]) - .with_name(format!("dynamic_{step}")) + re_types::archetypes::SeriesPoints::new() + .with_colors([color_gradient0(step)]) + .with_marker_sizes([(32.0 - step as f32) * 0.5]) + .with_markers([MARKER_LIST[step as usize % MARKER_LIST.len()]]) + .with_names([format!("dynamic_{step}")]) }; let (scalars_static, scalars_dynamic) = scalars_for_properties_test(step, multiple_scalars); diff --git a/docs/content/getting-started/configure-the-viewer/through-code-tutorial.md b/docs/content/getting-started/configure-the-viewer/through-code-tutorial.md index 8674c7f4f25b..1e9135ed3677 100644 --- a/docs/content/getting-started/configure-the-viewer/through-code-tutorial.md +++ b/docs/content/getting-started/configure-the-viewer/through-code-tutorial.md @@ -79,15 +79,15 @@ brand_colors = { } -def style_plot(symbol: str) -> rr.SeriesLine: - return rr.SeriesLine( +def style_plot(symbol: str) -> rr.SeriesLines: + return rr.SeriesLines( color=brand_colors[symbol], name=symbol, ) -def style_peak(symbol: str) -> rr.SeriesPoint: - return rr.SeriesPoint( +def style_peak(symbol: str) -> rr.SeriesPoints: + return rr.SeriesPoints( color=0xFF0000FF, name=f"{symbol} (peak)", marker="Up", @@ -154,9 +154,9 @@ def main() -> None: # Log the stock state over the course of the day for row in hist.itertuples(): rr.set_time("time", duration=row.Index) - rr.log(f"stocks/{symbol}/{day}", rr.Scalar(row.High)) + rr.log(f"stocks/{symbol}/{day}", rr.Scalars(row.High)) if row.Index == peak: - rr.log(f"stocks/{symbol}/peaks/{day}", rr.Scalar(row.High)) + rr.log(f"stocks/{symbol}/peaks/{day}", rr.Scalars(row.High)) if __name__ == "__main__": diff --git a/docs/content/getting-started/data-out/analyze-and-send.md b/docs/content/getting-started/data-out/analyze-and-send.md index 1e124d6c3e05..af595e7c009e 100644 --- a/docs/content/getting-started/data-out/analyze-and-send.md +++ b/docs/content/getting-started/data-out/analyze-and-send.md @@ -47,7 +47,7 @@ Here is how to send the data as a scalar: rr.send_columns( "/jaw_open_state", indexes=[rr.TimeColumn("frame_nr", sequence=df["frame_nr"])], - columns=rr.Scalar.columns(scalar=df["jawOpenState"]), + columns=rr.Scalars.columns(scalars=df["jawOpenState"]), ) ``` diff --git a/docs/content/howto/integrations/ros2-nav-turtlebot.md b/docs/content/howto/integrations/ros2-nav-turtlebot.md index 5b5cd3a0f4f8..d0e6986aa396 100644 --- a/docs/content/howto/integrations/ros2-nav-turtlebot.md +++ b/docs/content/howto/integrations/ros2-nav-turtlebot.md @@ -214,9 +214,9 @@ Note that because we previously called `set_time_nanos` in this callback, this t be logged to the same point on the timeline as the data, using a timestamp looked up from TF at the matching timepoint. -### Odometry to rr.Scalar and rr.Transform3D +### Odometry to rr.Scalars and rr.Transform3D -When receiving odometry messages, we log the linear and angular velocities using `rr.Scalar`. +When receiving odometry messages, we log the linear and angular velocities using `rr.Scalars`. Additionally, since we know that odometry will also update the `map/robot` transform, we use this as a cue to look up the corresponding transform and log it. @@ -227,8 +227,8 @@ def odom_callback(self, odom: Odometry) -> None: rr.set_time("ros_time", timestamp=np.datetime64(time.nanoseconds, "ns")) # Capture time-series data for the linear and angular velocities - rr.log("odometry/vel", rr.Scalar(odom.twist.twist.linear.x)) - rr.log("odometry/ang_vel", rr.Scalar(odom.twist.twist.angular.z)) + rr.log("odometry/vel", rr.Scalars(odom.twist.twist.linear.x)) + rr.log("odometry/ang_vel", rr.Scalars(odom.twist.twist.angular.z)) # Update the robot pose itself via TF self.log_tf_as_transform3d("map/robot", time) diff --git a/docs/content/reference/migration/migration-0-17.md b/docs/content/reference/migration/migration-0-17.md index afb233d19080..2f6692f46102 100644 --- a/docs/content/reference/migration/migration-0-17.md +++ b/docs/content/reference/migration/migration-0-17.md @@ -35,10 +35,10 @@ See [Visualizers and Overrides](../../concepts/visualizers-and-overrides.md) for This release introduces new Python APIs to set component overrides, visualizer overrides, and component defaults from code. Depending on your use-case, these new APIs become the preferred way of styling views. -For example, setting color and enabling the `SeriesPoint` visualizer was previously done using `rr.log()`: +For example, setting color and enabling the `SeriesPoints` visualizer was previously done using `rr.log()`: ```python -rr.log("data", rr.SeriesPoint(color=[255, 255, 0]), static=True) +rr.log("data", rr.SeriesPoints(colors=[255, 255, 0]), static=True) for t in range(1000): rr.set_time_sequence("frame_nr", t) @@ -61,7 +61,7 @@ rr.send_blueprint( origin="data", overrides={ "data": [ - rr.blueprint.VisualizerOverrides("SeriesPoint"), + rr.blueprint.VisualizerOverrides("SeriesPoints"), rr.components.Color([255, 255, 0]) ] }, diff --git a/docs/content/reference/migration/migration-0-23.md b/docs/content/reference/migration/migration-0-23.md index 6a305b3f6647..96ec3319c160 100644 --- a/docs/content/reference/migration/migration-0-23.md +++ b/docs/content/reference/migration/migration-0-23.md @@ -212,7 +212,7 @@ rrb.TimeSeriesView( origin="/classification", overrides={ "classification/line": [rr.components.Color([255, 255, 0]), rr.components.StrokeWidth(3.0)], - "classification/samples": [rrb.VisualizerOverrides("SeriesPoint")], # This ensures that the `SeriesPoint` visualizers is used for this entity. + "classification/samples": [rrb.VisualizerOverrides("SeriesPoints")], # This ensures that the `SeriesPoints` visualizers is used for this entity. }, ), # … @@ -224,16 +224,16 @@ rrb.TimeSeriesView( name="Trig", origin="/trig", overrides={ - "/trig/sin": rr.SeriesLine.from_fields(color=[255, 0, 0], name="sin(0.01t)"), - "/trig/cos": rr.SeriesLine.from_fields(color=[0, 255, 0], name="cos(0.01t)"), + "/trig/sin": rr.SeriesLines.from_fields(colors=[255, 0, 0], names="sin(0.01t)"), + "/trig/cos": rr.SeriesLines.from_fields(colors=[0, 255, 0], names="cos(0.01t)"), }, ), rrb.TimeSeriesView( name="Classification", origin="/classification", overrides={ - "classification/line": rr.SeriesLine.from_fields(color=[255, 255, 0], width=3.0), - "classification/samples": rrb.VisualizerOverrides("SeriesPoint"), # This ensures that the `SeriesPoint` visualizers is used for this entity. + "classification/line": rr.SeriesLines.from_fields(colors=[255, 255, 0], widths=3.0), + "classification/samples": rrb.VisualizerOverrides("SeriesPoints"), # This ensures that the `SeriesPoints` visualizers is used for this entity. }, ), # … @@ -335,3 +335,31 @@ overrides={ } # … ``` + +## Types for time series plots are now plural + +The `Scalar`/`SeriesPoints`/`SeriesLines` archetypess have been deprecated in favor of +`Scalars`/`SeriesPoints`/`SeriesLines` since you can now have a multiple +scatter plots or lines on the same archetype. + + +Before: +```py +rr.log("trig/sin", rr.SeriesLines(color=[s0, 255, 0], name="cos(0.01t)", width=4), static=True) + +for t in range(int(tau * 2 * 100.0)): + rr.set_time("step", sequence=t) + rr.log("trig/sin", rr.Scalar(sin(float(t) / 100.0))) +``` + +After: +```py +rr.log("trig/sin", rr.SeriesLines(colors=[255, 0, 0], names="sin(0.01t)", widths=2), static=True) + +for t in range(int(tau * 2 * 100.0)): + rr.set_time("step", sequence=t) + rr.log("trig/sin", rr.Scalars(sin(float(t) / 100.0))) +``` + + +The old types still work for the moment but will be removed in a future release. diff --git a/docs/content/reference/types/archetypes.md b/docs/content/reference/types/archetypes.md index d28e72880137..64a959324cd4 100644 --- a/docs/content/reference/types/archetypes.md +++ b/docs/content/reference/types/archetypes.md @@ -33,9 +33,12 @@ This page lists all built-in archetypes. ## Plotting * [`BarChart`](archetypes/bar_chart.md): A bar chart. -* [`Scalar`](archetypes/scalar.md): A double-precision scalar, e.g. for use for time-series plots. -* [`SeriesLine`](archetypes/series_line.md): Define the style properties for a line series in a chart. -* [`SeriesPoint`](archetypes/series_point.md): Define the style properties for a point series in a chart. +* ⚠️ _deprecated_ [`Scalar`](archetypes/scalar.md): A double-precision scalar, e.g. for use for time-series plots. +* [`Scalars`](archetypes/scalars.md): One or more double-precision scalar values, e.g. for use for time-series plots. +* ⚠️ _deprecated_ [`SeriesLine`](archetypes/series_line.md): Define the style properties for a line series in a chart. +* [`SeriesLines`](archetypes/series_lines.md): Define the style properties for one or more line series in a chart. +* ⚠️ _deprecated_ [`SeriesPoint`](archetypes/series_point.md): Define the style properties for a point series in a chart. +* [`SeriesPoints`](archetypes/series_points.md): Define the style properties for one or more point series (scatter plot) in a chart. ## Spatial 2D diff --git a/docs/content/reference/types/archetypes/.gitattributes b/docs/content/reference/types/archetypes/.gitattributes index 3b28a85e0ee8..981c3b9ea63f 100644 --- a/docs/content/reference/types/archetypes/.gitattributes +++ b/docs/content/reference/types/archetypes/.gitattributes @@ -28,9 +28,12 @@ points2d.md linguist-generated=true points3d.md linguist-generated=true recording_properties.md linguist-generated=true scalar.md linguist-generated=true +scalars.md linguist-generated=true segmentation_image.md linguist-generated=true series_line.md linguist-generated=true +series_lines.md linguist-generated=true series_point.md linguist-generated=true +series_points.md linguist-generated=true tensor.md linguist-generated=true text_document.md linguist-generated=true text_log.md linguist-generated=true diff --git a/docs/content/reference/types/archetypes/scalar.md b/docs/content/reference/types/archetypes/scalar.md index 38c2bfa6967a..2c1771d15185 100644 --- a/docs/content/reference/types/archetypes/scalar.md +++ b/docs/content/reference/types/archetypes/scalar.md @@ -1,15 +1,18 @@ --- -title: "Scalar" +title: "Scalar (deprecated)" --- +**⚠️ This type is deprecated and may be removed in future versions** +Use `Scalars` instead. + A double-precision scalar, e.g. for use for time-series plots. The current timeline value will be used for the time/X-axis, hence scalars -cannot be static. +should not be static. When used to produce a plot, this archetype is used to provide the data that -is referenced by [`archetypes.SeriesLine`](https://rerun.io/docs/reference/types/archetypes/series_line) or [`archetypes.SeriesPoint`](https://rerun.io/docs/reference/types/archetypes/series_point). You can do +is referenced by [`archetypes.SeriesLines`](https://rerun.io/docs/reference/types/archetypes/series_lines?speculative-link) or [`archetypes.SeriesPoints`](https://rerun.io/docs/reference/types/archetypes/series_points?speculative-link). You can do this by logging both archetypes to the same path, or alternatively configuring the plot-specific archetypes through the blueprint. @@ -30,9 +33,9 @@ the plot-specific archetypes through the blueprint. ### Simple line plot -snippet: archetypes/scalar_simple +snippet: archetypes/scalars_simple - + @@ -42,9 +45,9 @@ snippet: archetypes/scalar_simple ### Multiple time series plots -snippet: archetypes/scalar_multiple_plots +snippet: archetypes/scalars_multiple_plots - + @@ -54,9 +57,9 @@ snippet: archetypes/scalar_multiple_plots ### Update a scalar over time -snippet: archetypes/scalar_row_updates +snippet: archetypes/scalars_row_updates - + @@ -66,9 +69,9 @@ snippet: archetypes/scalar_row_updates ### Update a scalar over time, in a single operation -snippet: archetypes/scalar_column_updates +snippet: archetypes/scalars_column_updates - + diff --git a/docs/content/reference/types/archetypes/scalars.md b/docs/content/reference/types/archetypes/scalars.md new file mode 100644 index 000000000000..462a8d8f1115 --- /dev/null +++ b/docs/content/reference/types/archetypes/scalars.md @@ -0,0 +1,79 @@ +--- +title: "Scalars" +--- + + +One or more double-precision scalar values, e.g. for use for time-series plots. + +The current timeline value will be used for the time/X-axis, hence scalars +should not be static. +Number of scalars per timestamp is expected to be the same over time. + +When used to produce a plot, this archetype is used to provide the data that +is referenced by [`archetypes.SeriesLines`](https://rerun.io/docs/reference/types/archetypes/series_lines?speculative-link) or [`archetypes.SeriesPoints`](https://rerun.io/docs/reference/types/archetypes/series_points?speculative-link). You can do +this by logging both archetypes to the same path, or alternatively configuring +the plot-specific archetypes through the blueprint. + +## Components + +**Required**: [`Scalar`](../components/scalar.md) + +## Shown in +* [TimeSeriesView](../views/time_series_view.md) +* [DataframeView](../views/dataframe_view.md) + +## API reference links + * 🌊 [C++ API docs for `Scalars`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1Scalars.html?speculative-link) + * 🐍 [Python API docs for `Scalars`](https://ref.rerun.io/docs/python/stable/common/archetypes?speculative-link#rerun.archetypes.Scalars) + * 🦀 [Rust API docs for `Scalars`](https://docs.rs/rerun/latest/rerun/archetypes/struct.Scalars.html?speculative-link) + +## Examples + +### Simple line plot + +snippet: archetypes/scalars_simple + + + + + + + + + +### Multiple time series plots + +snippet: archetypes/scalars_multiple_plots + + + + + + + + + +### Update a scalar over time + +snippet: archetypes/scalars_row_updates + + + + + + + + + +### Update a scalar over time, in a single operation + +snippet: archetypes/scalars_column_updates + + + + + + + + + diff --git a/docs/content/reference/types/archetypes/series_line.md b/docs/content/reference/types/archetypes/series_line.md index a6e553ce1d39..23a917c70ade 100644 --- a/docs/content/reference/types/archetypes/series_line.md +++ b/docs/content/reference/types/archetypes/series_line.md @@ -1,13 +1,16 @@ --- -title: "SeriesLine" +title: "SeriesLine (deprecated)" --- +**⚠️ This type is deprecated and may be removed in future versions** +Use `SeriesLines` instead. + Define the style properties for a line series in a chart. This archetype only provides styling information and should be logged as static when possible. The underlying data needs to be logged to the same entity-path using -[`archetypes.Scalar`](https://rerun.io/docs/reference/types/archetypes/scalar). +[`archetypes.Scalars`](https://rerun.io/docs/reference/types/archetypes/scalars?speculative-link). ## Components @@ -26,9 +29,9 @@ when possible. The underlying data needs to be logged to the same entity-path us ### Line series -snippet: archetypes/series_line_style +snippet: archetypes/series_lines_style - + diff --git a/docs/content/reference/types/archetypes/series_lines.md b/docs/content/reference/types/archetypes/series_lines.md new file mode 100644 index 000000000000..f940ee980c83 --- /dev/null +++ b/docs/content/reference/types/archetypes/series_lines.md @@ -0,0 +1,41 @@ +--- +title: "SeriesLines" +--- + + +Define the style properties for one or more line series in a chart. + +This archetype only provides styling information. +Changes over time are supported for most but not all its fields (see respective fields for details), +it's generally recommended to log this type as static. + +The underlying data needs to be logged to the same entity-path using [`archetypes.Scalars`](https://rerun.io/docs/reference/types/archetypes/scalars?speculative-link). +Dimensionality of the scalar arrays logged at each time point is assumed to be the same over time. + +## Components + +**Optional**: [`Color`](../components/color.md), [`StrokeWidth`](../components/stroke_width.md), [`Name`](../components/name.md), [`SeriesVisible`](../components/series_visible.md), [`AggregationPolicy`](../components/aggregation_policy.md) + +## Shown in +* [TimeSeriesView](../views/time_series_view.md) +* [DataframeView](../views/dataframe_view.md) + +## API reference links + * 🌊 [C++ API docs for `SeriesLines`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1SeriesLines.html?speculative-link) + * 🐍 [Python API docs for `SeriesLines`](https://ref.rerun.io/docs/python/stable/common/archetypes?speculative-link#rerun.archetypes.SeriesLines) + * 🦀 [Rust API docs for `SeriesLines`](https://docs.rs/rerun/latest/rerun/archetypes/struct.SeriesLines.html?speculative-link) + +## Example + +### Line series + +snippet: archetypes/series_lines_style + + + + + + + + + diff --git a/docs/content/reference/types/archetypes/series_point.md b/docs/content/reference/types/archetypes/series_point.md index a5ea252b87d6..6c38ca40c8b0 100644 --- a/docs/content/reference/types/archetypes/series_point.md +++ b/docs/content/reference/types/archetypes/series_point.md @@ -1,13 +1,16 @@ --- -title: "SeriesPoint" +title: "SeriesPoint (deprecated)" --- +**⚠️ This type is deprecated and may be removed in future versions** +Use `SeriesPoints` instead. + Define the style properties for a point series in a chart. This archetype only provides styling information and should be logged as static when possible. The underlying data needs to be logged to the same entity-path using -[`archetypes.Scalar`](https://rerun.io/docs/reference/types/archetypes/scalar). +[`archetypes.Scalars`](https://rerun.io/docs/reference/types/archetypes/scalars?speculative-link). ## Components @@ -26,9 +29,9 @@ when possible. The underlying data needs to be logged to the same entity-path us ### Point series -snippet: archetypes/series_point_style +snippet: archetypes/series_points_style - + diff --git a/docs/content/reference/types/archetypes/series_points.md b/docs/content/reference/types/archetypes/series_points.md new file mode 100644 index 000000000000..d8a1585963b8 --- /dev/null +++ b/docs/content/reference/types/archetypes/series_points.md @@ -0,0 +1,41 @@ +--- +title: "SeriesPoints" +--- + + +Define the style properties for one or more point series (scatter plot) in a chart. + +This archetype only provides styling information. +Changes over time are supported for most but not all its fields (see respective fields for details), +it's generally recommended to log this type as static. + +The underlying data needs to be logged to the same entity-path using [`archetypes.Scalars`](https://rerun.io/docs/reference/types/archetypes/scalars?speculative-link). +Dimensionality of the scalar arrays logged at each time point is assumed to be the same over time. + +## Components + +**Optional**: [`Color`](../components/color.md), [`MarkerShape`](../components/marker_shape.md), [`Name`](../components/name.md), [`SeriesVisible`](../components/series_visible.md), [`MarkerSize`](../components/marker_size.md) + +## Shown in +* [TimeSeriesView](../views/time_series_view.md) +* [DataframeView](../views/dataframe_view.md) + +## API reference links + * 🌊 [C++ API docs for `SeriesPoints`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1SeriesPoints.html?speculative-link) + * 🐍 [Python API docs for `SeriesPoints`](https://ref.rerun.io/docs/python/stable/common/archetypes?speculative-link#rerun.archetypes.SeriesPoints) + * 🦀 [Rust API docs for `SeriesPoints`](https://docs.rs/rerun/latest/rerun/archetypes/struct.SeriesPoints.html?speculative-link) + +## Example + +### Point series + +snippet: archetypes/series_points_style + + + + + + + + + diff --git a/docs/content/reference/types/components/aggregation_policy.md b/docs/content/reference/types/components/aggregation_policy.md index a6e5f8a50e98..117e13063abe 100644 --- a/docs/content/reference/types/components/aggregation_policy.md +++ b/docs/content/reference/types/components/aggregation_policy.md @@ -45,3 +45,4 @@ uint8 ## Used by * [`SeriesLine`](../archetypes/series_line.md) +* [`SeriesLines`](../archetypes/series_lines.md?speculative-link) diff --git a/docs/content/reference/types/components/color.md b/docs/content/reference/types/components/color.md index 835488c2c0cf..dfde8bcf5471 100644 --- a/docs/content/reference/types/components/color.md +++ b/docs/content/reference/types/components/color.md @@ -41,5 +41,7 @@ uint32 * [`Points2D`](../archetypes/points2d.md) * [`Points3D`](../archetypes/points3d.md) * [`SeriesLine`](../archetypes/series_line.md) +* [`SeriesLines`](../archetypes/series_lines.md?speculative-link) * [`SeriesPoint`](../archetypes/series_point.md) +* [`SeriesPoints`](../archetypes/series_points.md?speculative-link) * [`TextLog`](../archetypes/text_log.md) diff --git a/docs/content/reference/types/components/marker_shape.md b/docs/content/reference/types/components/marker_shape.md index 2bfb90acc6c1..eff91a79983c 100644 --- a/docs/content/reference/types/components/marker_shape.md +++ b/docs/content/reference/types/components/marker_shape.md @@ -51,3 +51,4 @@ uint8 ## Used by * [`SeriesPoint`](../archetypes/series_point.md) +* [`SeriesPoints`](../archetypes/series_points.md?speculative-link) diff --git a/docs/content/reference/types/components/marker_size.md b/docs/content/reference/types/components/marker_size.md index 8a7673d6913f..658a77a80f20 100644 --- a/docs/content/reference/types/components/marker_size.md +++ b/docs/content/reference/types/components/marker_size.md @@ -23,3 +23,4 @@ float32 ## Used by * [`SeriesPoint`](../archetypes/series_point.md) +* [`SeriesPoints`](../archetypes/series_points.md?speculative-link) diff --git a/docs/content/reference/types/components/name.md b/docs/content/reference/types/components/name.md index e16269c5293d..0adc95ca1831 100644 --- a/docs/content/reference/types/components/name.md +++ b/docs/content/reference/types/components/name.md @@ -24,4 +24,6 @@ utf8 * [`RecordingProperties`](../archetypes/recording_properties.md?speculative-link) * [`SeriesLine`](../archetypes/series_line.md) +* [`SeriesLines`](../archetypes/series_lines.md?speculative-link) * [`SeriesPoint`](../archetypes/series_point.md) +* [`SeriesPoints`](../archetypes/series_points.md?speculative-link) diff --git a/docs/content/reference/types/components/scalar.md b/docs/content/reference/types/components/scalar.md index c85331c1eac4..8f5fe42640e5 100644 --- a/docs/content/reference/types/components/scalar.md +++ b/docs/content/reference/types/components/scalar.md @@ -25,3 +25,4 @@ float64 ## Used by * [`Scalar`](../archetypes/scalar.md) +* [`Scalars`](../archetypes/scalars.md?speculative-link) diff --git a/docs/content/reference/types/components/series_visible.md b/docs/content/reference/types/components/series_visible.md index 4facaeadb51f..150c3fd7046e 100644 --- a/docs/content/reference/types/components/series_visible.md +++ b/docs/content/reference/types/components/series_visible.md @@ -25,4 +25,6 @@ boolean ## Used by * [`SeriesLine`](../archetypes/series_line.md) +* [`SeriesLines`](../archetypes/series_lines.md?speculative-link) * [`SeriesPoint`](../archetypes/series_point.md) +* [`SeriesPoints`](../archetypes/series_points.md?speculative-link) diff --git a/docs/content/reference/types/components/stroke_width.md b/docs/content/reference/types/components/stroke_width.md index 980cba7727f8..d3e046c9de52 100644 --- a/docs/content/reference/types/components/stroke_width.md +++ b/docs/content/reference/types/components/stroke_width.md @@ -23,3 +23,4 @@ float32 ## Used by * [`SeriesLine`](../archetypes/series_line.md) +* [`SeriesLines`](../archetypes/series_lines.md?speculative-link) diff --git a/docs/content/reference/types/views.md b/docs/content/reference/types/views.md index 8f725c6ba452..03488c45df2a 100644 --- a/docs/content/reference/types/views.md +++ b/docs/content/reference/types/views.md @@ -16,5 +16,5 @@ Views are the panels shown in the viewer's viewport and the primary means of ins * [`TensorView`](views/tensor_view.md): A view on a tensor of any dimensionality. * [`TextDocumentView`](views/text_document_view.md): A view of a single text document, for use with [`archetypes.TextDocument`](https://rerun.io/docs/reference/types/archetypes/text_document). * [`TextLogView`](views/text_log_view.md): A view of a text log, for use with [`archetypes.TextLog`](https://rerun.io/docs/reference/types/archetypes/text_log). -* [`TimeSeriesView`](views/time_series_view.md): A time series view for scalars over time, for use with [`archetypes.Scalar`](https://rerun.io/docs/reference/types/archetypes/scalar). +* [`TimeSeriesView`](views/time_series_view.md): A time series view for scalars over time, for use with [`archetypes.Scalars`](https://rerun.io/docs/reference/types/archetypes/scalars?speculative-link). diff --git a/docs/content/reference/types/views/time_series_view.md b/docs/content/reference/types/views/time_series_view.md index d862d5a4808f..bd32951f1e95 100644 --- a/docs/content/reference/types/views/time_series_view.md +++ b/docs/content/reference/types/views/time_series_view.md @@ -3,7 +3,7 @@ title: "TimeSeriesView" --- -A time series view for scalars over time, for use with [`archetypes.Scalar`](https://rerun.io/docs/reference/types/archetypes/scalar). +A time series view for scalars over time, for use with [`archetypes.Scalars`](https://rerun.io/docs/reference/types/archetypes/scalars?speculative-link). ## Properties @@ -45,6 +45,9 @@ snippet: views/timeseries * [`Clear`](../archetypes/clear.md) * [`Scalar`](../archetypes/scalar.md) +* [`Scalars`](../archetypes/scalars.md) * [`SeriesLine`](../archetypes/series_line.md) +* [`SeriesLines`](../archetypes/series_lines.md) * [`SeriesPoint`](../archetypes/series_point.md) +* [`SeriesPoints`](../archetypes/series_points.md) diff --git a/docs/snippets/INDEX.md b/docs/snippets/INDEX.md index 53dd6303de99..9c371f64423a 100644 --- a/docs/snippets/INDEX.md +++ b/docs/snippets/INDEX.md @@ -22,10 +22,8 @@ Use it to quickly find copy-pastable snippets of code for any Rerun feature you' | ------- | ------- | ----------- | :----: | :--: | :-------: | | **Setting recording properties** | `recording_properties` | Sets the recording properties | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/recording_properties.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/recording_properties.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/recording_properties.cpp) | | **Update rows** | `arrows3d_row_updates` | Update a set of vectors over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_row_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_row_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_row_updates.cpp) | -| **Update rows** | `scalar_row_updates` | Update a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_row_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_row_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_row_updates.cpp) | | **Update rows** | `points3d_row_updates` | Update a point cloud over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_row_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_row_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_row_updates.cpp) | | **Update rows** | `transform3d_row_updates` | Update a transform over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_row_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_row_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_row_updates.cpp) | -| **Update columns** | `scalar_column_updates` | Update a scalar over time, in a single operation | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_column_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_column_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_column_updates.cpp) | | **Update columns** | `points3d_column_updates` | Update a point cloud over time, in a single operation | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_column_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_column_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_column_updates.cpp) | | **Update columns** | `transform3d_column_updates` | Update a transform over time, in a single operation | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_column_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_column_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_column_updates.cpp) | | **Update columns** | `image_column_updates` | Update an image over time, in a single operation | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_column_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_column_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_column_updates.cpp) | @@ -159,24 +157,25 @@ _All snippets, organized by the [`Archetype`](https://rerun.io/docs/reference/ty | **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `quick_start⁠/⁠quick_start_spawn` | Spawn a viewer and log some data | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/quick_start/quick_start_spawn.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/quick_start/quick_start_spawn.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/quick_start/quick_start_spawn.cpp) | | **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `tutorials⁠/⁠timelines_example` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/timelines_example.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/timelines_example.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/timelines_example.cpp) | | **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `views⁠/⁠spatial3d` | Use a blueprint to customize a Spatial3DView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/spatial3d.py) | | | -| **[`Scalar`](https://rerun.io/docs/reference/types/archetypes/scalar)** | `archetypes⁠/⁠scalar_simple` | Log a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_simple.cpp) | -| **[`Scalar`](https://rerun.io/docs/reference/types/archetypes/scalar)** | `archetypes⁠/⁠scalar_row_updates` | Update a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_row_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_row_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_row_updates.cpp) | -| **[`Scalar`](https://rerun.io/docs/reference/types/archetypes/scalar)** | `archetypes⁠/⁠scalar_multiple_plots` | Log a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_multiple_plots.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_multiple_plots.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_multiple_plots.cpp) | -| **[`Scalar`](https://rerun.io/docs/reference/types/archetypes/scalar)** | `archetypes⁠/⁠scalar_column_updates` | Update a scalar over time, in a single operation | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_column_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_column_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_column_updates.cpp) | -| **[`Scalar`](https://rerun.io/docs/reference/types/archetypes/scalar)** | `archetypes⁠/⁠series_line_style` | Log a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_line_style.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_line_style.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_line_style.cpp) | -| **[`Scalar`](https://rerun.io/docs/reference/types/archetypes/scalar)** | `archetypes⁠/⁠series_point_style` | Log a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_point_style.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_point_style.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_point_style.cpp) | -| **[`Scalar`](https://rerun.io/docs/reference/types/archetypes/scalar)** | `tutorials⁠/⁠fixed_window_plot` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/fixed_window_plot.py) | | | -| **[`Scalar`](https://rerun.io/docs/reference/types/archetypes/scalar)** | `tutorials⁠/⁠visualizer-overrides` | Log a scalar over time and override the visualizer | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/visualizer-overrides.py) | | | -| **[`Scalar`](https://rerun.io/docs/reference/types/archetypes/scalar)** | `views⁠/⁠dataframe` | Use a blueprint to customize a DataframeView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/dataframe.py) | | | -| **[`Scalar`](https://rerun.io/docs/reference/types/archetypes/scalar)** | `views⁠/⁠timeseries` | Use a blueprint to customize a TimeSeriesView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/timeseries.py) | | | +| **[`Scalars`](https://rerun.io/docs/reference/types/archetypes/scalars)** | `archetypes⁠/⁠scalars_simple` | Log a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalars_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalars_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalars_simple.cpp) | +| **[`Scalars`](https://rerun.io/docs/reference/types/archetypes/scalars)** | `archetypes⁠/⁠scalars_row_updates` | Update a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalars_row_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalars_row_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalars_row_updates.cpp) | +| **[`Scalars`](https://rerun.io/docs/reference/types/archetypes/scalars)** | `archetypes⁠/⁠scalars_multiple_plots` | Log a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalars_multiple_plots.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalars_multiple_plots.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalars_multiple_plots.cpp) | +| **[`Scalars`](https://rerun.io/docs/reference/types/archetypes/scalars)** | `archetypes⁠/⁠scalars_column_updates` | Update a scalar over time, in a single operation | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalars_column_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalars_column_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalars_column_updates.cpp) | +| **[`Scalars`](https://rerun.io/docs/reference/types/archetypes/scalars)** | `archetypes⁠/⁠series_lines_style` | Log a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_lines_style.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_lines_style.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_lines_style.cpp) | +| **[`Scalars`](https://rerun.io/docs/reference/types/archetypes/scalars)** | `archetypes⁠/⁠series_points_style` | Log a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_points_style.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_points_style.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_points_style.cpp) | +| **[`Scalars`](https://rerun.io/docs/reference/types/archetypes/scalars)** | `tutorials⁠/⁠data_out` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/data_out.py) | | | +| **[`Scalars`](https://rerun.io/docs/reference/types/archetypes/scalars)** | `tutorials⁠/⁠fixed_window_plot` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/fixed_window_plot.py) | | | +| **[`Scalars`](https://rerun.io/docs/reference/types/archetypes/scalars)** | `tutorials⁠/⁠visualizer-overrides` | Log a scalar over time and override the visualizer | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/visualizer-overrides.py) | | | +| **[`Scalars`](https://rerun.io/docs/reference/types/archetypes/scalars)** | `views⁠/⁠dataframe` | Use a blueprint to customize a DataframeView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/dataframe.py) | | | +| **[`Scalars`](https://rerun.io/docs/reference/types/archetypes/scalars)** | `views⁠/⁠timeseries` | Use a blueprint to customize a TimeSeriesView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/timeseries.py) | | | | **[`SegmentationImage`](https://rerun.io/docs/reference/types/archetypes/segmentation_image)** | `archetypes⁠/⁠segmentation_image_simple` | Create and log a segmentation image | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/segmentation_image_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/segmentation_image_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/segmentation_image_simple.cpp) | | **[`SegmentationImage`](https://rerun.io/docs/reference/types/archetypes/segmentation_image)** | `archetypes⁠/⁠annotation_context_segmentation` | Log a segmentation image with annotations | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/annotation_context_segmentation.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/annotation_context_segmentation.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/annotation_context_segmentation.cpp) | -| **[`SeriesLine`](https://rerun.io/docs/reference/types/archetypes/series_line)** | `archetypes⁠/⁠series_line_style` | Log a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_line_style.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_line_style.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_line_style.cpp) | -| **[`SeriesLine`](https://rerun.io/docs/reference/types/archetypes/series_line)** | `archetypes⁠/⁠scalar_multiple_plots` | Log a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_multiple_plots.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_multiple_plots.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_multiple_plots.cpp) | -| **[`SeriesLine`](https://rerun.io/docs/reference/types/archetypes/series_line)** | `views⁠/⁠timeseries` | Use a blueprint to customize a TimeSeriesView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/timeseries.py) | | | -| **[`SeriesPoint`](https://rerun.io/docs/reference/types/archetypes/series_point)** | `archetypes⁠/⁠series_point_style` | Log a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_point_style.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_point_style.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_point_style.cpp) | -| **[`SeriesPoint`](https://rerun.io/docs/reference/types/archetypes/series_point)** | `archetypes⁠/⁠scalar_multiple_plots` | Log a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_multiple_plots.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_multiple_plots.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_multiple_plots.cpp) | -| **[`SeriesPoint`](https://rerun.io/docs/reference/types/archetypes/series_point)** | `tutorials⁠/⁠visualizer-overrides` | Log a scalar over time and override the visualizer | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/visualizer-overrides.py) | | | +| **[`SeriesLines`](https://rerun.io/docs/reference/types/archetypes/series_lines)** | `archetypes⁠/⁠series_lines_style` | Log a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_lines_style.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_lines_style.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_lines_style.cpp) | +| **[`SeriesLines`](https://rerun.io/docs/reference/types/archetypes/series_lines)** | `archetypes⁠/⁠scalars_multiple_plots` | Log a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalars_multiple_plots.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalars_multiple_plots.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalars_multiple_plots.cpp) | +| **[`SeriesLines`](https://rerun.io/docs/reference/types/archetypes/series_lines)** | `views⁠/⁠timeseries` | Use a blueprint to customize a TimeSeriesView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/timeseries.py) | | | +| **[`SeriesPoints`](https://rerun.io/docs/reference/types/archetypes/series_points)** | `archetypes⁠/⁠series_points_style` | Log a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_points_style.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_points_style.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/series_points_style.cpp) | +| **[`SeriesPoints`](https://rerun.io/docs/reference/types/archetypes/series_points)** | `archetypes⁠/⁠scalars_multiple_plots` | Log a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalars_multiple_plots.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalars_multiple_plots.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalars_multiple_plots.cpp) | +| **[`SeriesPoints`](https://rerun.io/docs/reference/types/archetypes/series_points)** | `tutorials⁠/⁠visualizer-overrides` | Log a scalar over time and override the visualizer | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/visualizer-overrides.py) | | | | **[`Tensor`](https://rerun.io/docs/reference/types/archetypes/tensor)** | `views⁠/⁠tensor` | Use a blueprint to show a tensor view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/tensor.py) | | | | **[`Tensor`](https://rerun.io/docs/reference/types/archetypes/tensor)** | `archetypes⁠/⁠tensor_simple` | Create and log a tensor | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/tensor_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/tensor_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/tensor_simple.cpp) | | **[`Tensor`](https://rerun.io/docs/reference/types/archetypes/tensor)** | `views⁠/⁠bar_chart` | Use a blueprint to show a bar chart | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/bar_chart.py) | | | diff --git a/docs/snippets/all/archetypes/scalar_column_updates.cpp b/docs/snippets/all/archetypes/scalars_column_updates.cpp similarity index 91% rename from docs/snippets/all/archetypes/scalar_column_updates.cpp rename to docs/snippets/all/archetypes/scalars_column_updates.cpp index a06f34475fb6..4960e9d48d43 100644 --- a/docs/snippets/all/archetypes/scalar_column_updates.cpp +++ b/docs/snippets/all/archetypes/scalars_column_updates.cpp @@ -24,6 +24,6 @@ int main() { rec.send_columns( "scalars", rerun::TimeColumn::from_sequence("step", std::move(times)), - rerun::Scalar().with_many_scalar(std::move(scalar_data)).columns() + rerun::Scalars(std::move(scalar_data)).columns() ); } diff --git a/docs/snippets/all/archetypes/scalar_column_updates.py b/docs/snippets/all/archetypes/scalars_column_updates.py similarity index 89% rename from docs/snippets/all/archetypes/scalar_column_updates.py rename to docs/snippets/all/archetypes/scalars_column_updates.py index 2cf43d2cd646..51cd00bad1b3 100644 --- a/docs/snippets/all/archetypes/scalar_column_updates.py +++ b/docs/snippets/all/archetypes/scalars_column_updates.py @@ -17,5 +17,5 @@ rr.send_columns( "scalars", indexes=[rr.TimeColumn("step", sequence=times)], - columns=rr.Scalar.columns(scalar=scalars), + columns=rr.Scalars.columns(scalars=scalars), ) diff --git a/docs/snippets/all/archetypes/scalar_column_updates.rs b/docs/snippets/all/archetypes/scalars_column_updates.rs similarity index 81% rename from docs/snippets/all/archetypes/scalar_column_updates.rs rename to docs/snippets/all/archetypes/scalars_column_updates.rs index 47c64974a667..63826596e3db 100644 --- a/docs/snippets/all/archetypes/scalar_column_updates.rs +++ b/docs/snippets/all/archetypes/scalars_column_updates.rs @@ -13,9 +13,7 @@ fn main() -> Result<(), Box> { rec.send_columns( "scalars", [times], - rerun::Scalar::update_fields() - .with_many_scalar(scalars) - .columns_of_unit_batches()?, + rerun::Scalars::new(scalars).columns_of_unit_batches()?, )?; Ok(()) diff --git a/docs/snippets/all/archetypes/scalar_multiple_plots.cpp b/docs/snippets/all/archetypes/scalars_multiple_plots.cpp similarity index 53% rename from docs/snippets/all/archetypes/scalar_multiple_plots.cpp rename to docs/snippets/all/archetypes/scalars_multiple_plots.cpp index 48b962c6370e..6f74b7f2e15a 100644 --- a/docs/snippets/all/archetypes/scalar_multiple_plots.cpp +++ b/docs/snippets/all/archetypes/scalars_multiple_plots.cpp @@ -15,20 +15,26 @@ int main() { // Set up plot styling: // They are logged static as they don't change over time and apply to all timelines. // Log two lines series under a shared root so that they show in the same plot by default. - rec.log_static("trig/sin", rerun::SeriesLine().with_color({255, 0, 0}).with_name("sin(0.01t)")); - rec.log_static("trig/cos", rerun::SeriesLine().with_color({0, 255, 0}).with_name("cos(0.01t)")); + rec.log_static( + "trig/sin", + rerun::SeriesLines().with_colors(rerun::Rgba32{255, 0, 0}).with_names("sin(0.01t)") + ); + rec.log_static( + "trig/cos", + rerun::SeriesLines().with_colors(rerun::Rgba32{0, 255, 0}).with_names("cos(0.01t)") + ); // Log scattered points under a different root so that they show in a different plot by default. - rec.log_static("scatter/lcg", rerun::SeriesPoint()); + rec.log_static("scatter/lcg", rerun::SeriesPoints()); // Log the data on a timeline called "step". for (int t = 0; t < static_cast(TAU * 2.0 * 100.0); ++t) { rec.set_time_sequence("step", t); - rec.log("trig/sin", rerun::Scalar(sin(t / 100.0))); - rec.log("trig/cos", rerun::Scalar(cos(static_cast(t) / 100.0f))); + rec.log("trig/sin", rerun::Scalars(sin(static_cast(t) / 100.0))); + rec.log("trig/cos", rerun::Scalars(cos(static_cast(t) / 100.0))); lcg_state = - 1140671485 * lcg_state + 128201163 % 16777216; // simple linear congruency generator - rec.log("scatter/lcg", rerun::Scalar(static_cast(lcg_state))); + (1140671485 * lcg_state + 128201163) % 16777216; // simple linear congruency generator + rec.log("scatter/lcg", rerun::Scalars(static_cast(lcg_state))); } } diff --git a/docs/snippets/all/archetypes/scalar_multiple_plots.py b/docs/snippets/all/archetypes/scalars_multiple_plots.py similarity index 63% rename from docs/snippets/all/archetypes/scalar_multiple_plots.py rename to docs/snippets/all/archetypes/scalars_multiple_plots.py index 171596cfb9e2..f697590120f4 100644 --- a/docs/snippets/all/archetypes/scalar_multiple_plots.py +++ b/docs/snippets/all/archetypes/scalars_multiple_plots.py @@ -11,17 +11,17 @@ # Set up plot styling: # They are logged as static as they don't change over time and apply to all timelines. # Log two lines series under a shared root so that they show in the same plot by default. -rr.log("trig/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)"), static=True) -rr.log("trig/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)"), static=True) +rr.log("trig/sin", rr.SeriesLines(colors=[255, 0, 0], names="sin(0.01t)"), static=True) +rr.log("trig/cos", rr.SeriesLines(colors=[0, 255, 0], names="cos(0.01t)"), static=True) # Log scattered points under a different root so that they show in a different plot by default. -rr.log("scatter/lcg", rr.SeriesPoint(), static=True) +rr.log("scatter/lcg", rr.SeriesPoints(), static=True) # Log the data on a timeline called "step". for t in range(int(tau * 2 * 100.0)): rr.set_time("step", sequence=t) - rr.log("trig/sin", rr.Scalar(sin(float(t) / 100.0))) - rr.log("trig/cos", rr.Scalar(cos(float(t) / 100.0))) + rr.log("trig/sin", rr.Scalars(sin(float(t) / 100.0))) + rr.log("trig/cos", rr.Scalars(cos(float(t) / 100.0))) lcg_state = (1140671485 * lcg_state + 128201163) % 16777216 # simple linear congruency generator - rr.log("scatter/lcg", rr.Scalar(lcg_state.astype(np.float64))) + rr.log("scatter/lcg", rr.Scalars(lcg_state.astype(np.float64))) diff --git a/docs/snippets/all/archetypes/scalar_multiple_plots.rs b/docs/snippets/all/archetypes/scalars_multiple_plots.rs similarity index 68% rename from docs/snippets/all/archetypes/scalar_multiple_plots.rs rename to docs/snippets/all/archetypes/scalars_multiple_plots.rs index 6e805aeaddd4..3616d183caf1 100644 --- a/docs/snippets/all/archetypes/scalar_multiple_plots.rs +++ b/docs/snippets/all/archetypes/scalars_multiple_plots.rs @@ -9,32 +9,32 @@ fn main() -> Result<(), Box> { // Log two lines series under a shared root so that they show in the same plot by default. rec.log_static( "trig/sin", - &rerun::SeriesLine::new() - .with_color([255, 0, 0]) - .with_name("sin(0.01t)"), + &rerun::SeriesLines::new() + .with_colors([[255, 0, 0]]) + .with_names(["sin(0.01t)"]), )?; rec.log_static( "trig/cos", - &rerun::SeriesLine::new() - .with_color([0, 255, 0]) - .with_name("cos(0.01t)"), + &rerun::SeriesLines::new() + .with_colors([[0, 255, 0]]) + .with_names(["cos(0.01t)"]), )?; // Log scattered points under a different root so that they show in a different plot by default. - rec.log_static("scatter/lcg", &rerun::SeriesPoint::new())?; + rec.log_static("scatter/lcg", &rerun::SeriesPoints::new())?; for t in 0..((std::f32::consts::TAU * 2.0 * 100.0) as i64) { rec.set_time_sequence("step", t); // Log two time series under a shared root so that they show in the same plot by default. - rec.log("trig/sin", &rerun::Scalar::new((t as f64 / 100.0).sin()))?; - rec.log("trig/cos", &rerun::Scalar::new((t as f64 / 100.0).cos()))?; + rec.log("trig/sin", &rerun::Scalars::one((t as f64 / 100.0).sin()))?; + rec.log("trig/cos", &rerun::Scalars::one((t as f64 / 100.0).cos()))?; // Log scattered points under a different root so that it shows in a different plot by default. lcg_state = (1140671485_i64 .wrapping_mul(lcg_state) .wrapping_add(128201163)) % 16777216; // simple linear congruency generator - rec.log("scatter/lcg", &rerun::Scalar::new(lcg_state as f64))?; + rec.log("scatter/lcg", &rerun::Scalars::one(lcg_state as f64))?; } Ok(()) diff --git a/docs/snippets/all/archetypes/scalar_row_updates.cpp b/docs/snippets/all/archetypes/scalars_row_updates.cpp similarity index 83% rename from docs/snippets/all/archetypes/scalar_row_updates.cpp rename to docs/snippets/all/archetypes/scalars_row_updates.cpp index 0873eff9699c..c295d7eb7763 100644 --- a/docs/snippets/all/archetypes/scalar_row_updates.cpp +++ b/docs/snippets/all/archetypes/scalars_row_updates.cpp @@ -12,6 +12,6 @@ int main() { for (int step = 0; step < 64; ++step) { rec.set_time_sequence("step", step); - rec.log("scalars", rerun::Scalar(sin(static_cast(step) / 10.0))); + rec.log("scalars", rerun::Scalars(sin(static_cast(step) / 10.0))); } } diff --git a/docs/snippets/all/archetypes/scalar_row_updates.py b/docs/snippets/all/archetypes/scalars_row_updates.py similarity index 85% rename from docs/snippets/all/archetypes/scalar_row_updates.py rename to docs/snippets/all/archetypes/scalars_row_updates.py index a67946501c89..e36b651a2102 100644 --- a/docs/snippets/all/archetypes/scalar_row_updates.py +++ b/docs/snippets/all/archetypes/scalars_row_updates.py @@ -14,4 +14,4 @@ for step in range(64): rr.set_time("step", sequence=step) - rr.log("scalars", rr.Scalar(math.sin(step / 10.0))) + rr.log("scalars", rr.Scalars(math.sin(step / 10.0))) diff --git a/docs/snippets/all/archetypes/scalar_row_updates.rs b/docs/snippets/all/archetypes/scalars_row_updates.rs similarity index 82% rename from docs/snippets/all/archetypes/scalar_row_updates.rs rename to docs/snippets/all/archetypes/scalars_row_updates.rs index 27eaddc1b5ed..06e08dc0ccb0 100644 --- a/docs/snippets/all/archetypes/scalar_row_updates.rs +++ b/docs/snippets/all/archetypes/scalars_row_updates.rs @@ -7,7 +7,7 @@ fn main() -> Result<(), Box> { for step in 0..64 { rec.set_time_sequence("step", step); - rec.log("scalars", &rerun::Scalar::new((step as f64 / 10.0).sin()))?; + rec.log("scalars", &rerun::Scalars::one((step as f64 / 10.0).sin()))?; } Ok(()) diff --git a/docs/snippets/all/archetypes/scalar_simple.cpp b/docs/snippets/all/archetypes/scalars_simple.cpp similarity index 79% rename from docs/snippets/all/archetypes/scalar_simple.cpp rename to docs/snippets/all/archetypes/scalars_simple.cpp index 9504a26f0dc3..6a8df06e2a03 100644 --- a/docs/snippets/all/archetypes/scalar_simple.cpp +++ b/docs/snippets/all/archetypes/scalars_simple.cpp @@ -11,6 +11,6 @@ int main() { // Log the data on a timeline called "step". for (int step = 0; step < 64; ++step) { rec.set_time_sequence("step", step); - rec.log("scalar", rerun::Scalar(std::sin(static_cast(step) / 10.0))); + rec.log("scalar", rerun::Scalars(std::sin(static_cast(step) / 10.0))); } } diff --git a/docs/snippets/all/archetypes/scalar_simple.py b/docs/snippets/all/archetypes/scalars_simple.py similarity index 79% rename from docs/snippets/all/archetypes/scalar_simple.py rename to docs/snippets/all/archetypes/scalars_simple.py index 3e4a29ea45f5..666cb8c82239 100644 --- a/docs/snippets/all/archetypes/scalar_simple.py +++ b/docs/snippets/all/archetypes/scalars_simple.py @@ -9,4 +9,4 @@ # Log the data on a timeline called "step". for step in range(64): rr.set_time("step", sequence=step) - rr.log("scalar", rr.Scalar(math.sin(step / 10.0))) + rr.log("scalar", rr.Scalars(math.sin(step / 10.0))) diff --git a/docs/snippets/all/archetypes/scalar_simple.rs b/docs/snippets/all/archetypes/scalars_simple.rs similarity index 79% rename from docs/snippets/all/archetypes/scalar_simple.rs rename to docs/snippets/all/archetypes/scalars_simple.rs index 8b000d397504..68b3466e9da3 100644 --- a/docs/snippets/all/archetypes/scalar_simple.rs +++ b/docs/snippets/all/archetypes/scalars_simple.rs @@ -6,7 +6,7 @@ fn main() -> Result<(), Box> { // Log the data on a timeline called "step". for step in 0..64 { rec.set_time_sequence("step", step); - rec.log("scalar", &rerun::Scalar::new((step as f64 / 10.0).sin()))?; + rec.log("scalar", &rerun::Scalars::one((step as f64 / 10.0).sin()))?; } Ok(()) diff --git a/docs/snippets/all/archetypes/series_line_style.cpp b/docs/snippets/all/archetypes/series_lines_style.cpp similarity index 61% rename from docs/snippets/all/archetypes/series_line_style.cpp rename to docs/snippets/all/archetypes/series_lines_style.cpp index f0a66197b8e5..cde9385a0bd7 100644 --- a/docs/snippets/all/archetypes/series_line_style.cpp +++ b/docs/snippets/all/archetypes/series_lines_style.cpp @@ -15,18 +15,24 @@ int main() { // Log two lines series under a shared root so that they show in the same plot by default. rec.log_static( "trig/sin", - rerun::SeriesLine().with_color({255, 0, 0}).with_name("sin(0.01t)").with_width(2) + rerun::SeriesLines() + .with_colors(rerun::Rgba32{255, 0, 0}) + .with_names("sin(0.01t)") + .with_widths(2.0f) ); rec.log_static( "trig/cos", - rerun::SeriesLine().with_color({0, 255, 0}).with_name("cos(0.01t)").with_width(4) + rerun::SeriesLines() + .with_colors(rerun::Rgba32{0, 255, 0}) + .with_names("cos(0.01t)") + .with_widths(4.0f) ); // Log the data on a timeline called "step". for (int t = 0; t < static_cast(TAU * 2.0 * 100.0); ++t) { rec.set_time_sequence("step", t); - rec.log("trig/sin", rerun::Scalar(sin(static_cast(t) / 100.0))); - rec.log("trig/cos", rerun::Scalar(cos(static_cast(t) / 100.0))); + rec.log("trig/sin", rerun::Scalars(sin(static_cast(t) / 100.0))); + rec.log("trig/cos", rerun::Scalars(cos(static_cast(t) / 100.0))); } } diff --git a/docs/snippets/all/archetypes/series_line_style.py b/docs/snippets/all/archetypes/series_lines_style.py similarity index 59% rename from docs/snippets/all/archetypes/series_line_style.py rename to docs/snippets/all/archetypes/series_lines_style.py index 9c11b7a516fe..e6a7b9c8b43f 100644 --- a/docs/snippets/all/archetypes/series_line_style.py +++ b/docs/snippets/all/archetypes/series_lines_style.py @@ -9,12 +9,12 @@ # Set up plot styling: # They are logged as static as they don't change over time and apply to all timelines. # Log two lines series under a shared root so that they show in the same plot by default. -rr.log("trig/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)", width=2), static=True) -rr.log("trig/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)", width=4), static=True) +rr.log("trig/sin", rr.SeriesLines(colors=[255, 0, 0], names="sin(0.01t)", widths=2), static=True) +rr.log("trig/cos", rr.SeriesLines(colors=[0, 255, 0], names="cos(0.01t)", widths=4), static=True) # Log the data on a timeline called "step". for t in range(int(tau * 2 * 100.0)): rr.set_time("step", sequence=t) - rr.log("trig/sin", rr.Scalar(sin(float(t) / 100.0))) - rr.log("trig/cos", rr.Scalar(cos(float(t) / 100.0))) + rr.log("trig/sin", rr.Scalars(sin(float(t) / 100.0))) + rr.log("trig/cos", rr.Scalars(cos(float(t) / 100.0))) diff --git a/docs/snippets/all/archetypes/series_line_style.rs b/docs/snippets/all/archetypes/series_lines_style.rs similarity index 61% rename from docs/snippets/all/archetypes/series_line_style.rs rename to docs/snippets/all/archetypes/series_lines_style.rs index 27754cd839aa..28a4cd36f51c 100644 --- a/docs/snippets/all/archetypes/series_line_style.rs +++ b/docs/snippets/all/archetypes/series_lines_style.rs @@ -8,25 +8,25 @@ fn main() -> Result<(), Box> { // Log two lines series under a shared root so that they show in the same plot by default. rec.log_static( "trig/sin", - &rerun::SeriesLine::new() - .with_color([255, 0, 0]) - .with_name("sin(0.01t)") - .with_width(2.0), + &rerun::SeriesLines::new() + .with_colors([[255, 0, 0]]) + .with_names(["sin(0.01t)"]) + .with_widths([2.0]), )?; rec.log_static( "trig/cos", - &rerun::SeriesLine::new() - .with_color([0, 255, 0]) - .with_name("cos(0.01t)") - .with_width(4.0), + &rerun::SeriesLines::new() + .with_colors([[0, 255, 0]]) + .with_names(["cos(0.01t)"]) + .with_widths([4.0]), )?; for t in 0..((std::f32::consts::TAU * 2.0 * 100.0) as i64) { rec.set_time_sequence("step", t); // Log two time series under a shared root so that they show in the same plot by default. - rec.log("trig/sin", &rerun::Scalar::new((t as f64 / 100.0).sin()))?; - rec.log("trig/cos", &rerun::Scalar::new((t as f64 / 100.0).cos()))?; + rec.log("trig/sin", &rerun::Scalars::one((t as f64 / 100.0).sin()))?; + rec.log("trig/cos", &rerun::Scalars::one((t as f64 / 100.0).cos()))?; } Ok(()) diff --git a/docs/snippets/all/archetypes/series_point_style.cpp b/docs/snippets/all/archetypes/series_points_style.cpp similarity index 54% rename from docs/snippets/all/archetypes/series_point_style.cpp rename to docs/snippets/all/archetypes/series_points_style.cpp index 6630943fa000..8b0e7af4d509 100644 --- a/docs/snippets/all/archetypes/series_point_style.cpp +++ b/docs/snippets/all/archetypes/series_points_style.cpp @@ -15,26 +15,26 @@ int main() { // Log two point series under a shared root so that they show in the same plot by default. rec.log_static( "trig/sin", - rerun::SeriesPoint() - .with_color({255, 0, 0}) - .with_name("sin(0.01t)") - .with_marker(rerun::components::MarkerShape::Circle) - .with_marker_size(4) + rerun::SeriesPoints() + .with_colors(rerun::Rgba32{255, 0, 0}) + .with_names("sin(0.01t)") + .with_markers(rerun::components::MarkerShape::Circle) + .with_marker_sizes(4.0f) ); rec.log_static( "trig/cos", - rerun::SeriesPoint() - .with_color({0, 255, 0}) - .with_name("cos(0.01t)") - .with_marker(rerun::components::MarkerShape::Cross) - .with_marker_size(2) + rerun::SeriesPoints() + .with_colors(rerun::Rgba32{0, 255, 0}) + .with_names("cos(0.01t)") + .with_markers(rerun::components::MarkerShape::Cross) + .with_marker_sizes(2.0f) ); // Log the data on a timeline called "step". for (int t = 0; t < static_cast(TAU * 2.0 * 10.0); ++t) { rec.set_time_sequence("step", t); - rec.log("trig/sin", rerun::Scalar(sin(static_cast(t) / 10.0))); - rec.log("trig/cos", rerun::Scalar(cos(static_cast(t) / 10.0))); + rec.log("trig/sin", rerun::Scalars(sin(static_cast(t) / 10.0))); + rec.log("trig/cos", rerun::Scalars(cos(static_cast(t) / 10.0))); } } diff --git a/docs/snippets/all/archetypes/series_point_style.py b/docs/snippets/all/archetypes/series_points_style.py similarity index 60% rename from docs/snippets/all/archetypes/series_point_style.py rename to docs/snippets/all/archetypes/series_points_style.py index f69657e806c5..a2abd512aa05 100644 --- a/docs/snippets/all/archetypes/series_point_style.py +++ b/docs/snippets/all/archetypes/series_points_style.py @@ -11,28 +11,29 @@ # Log two point series under a shared root so that they show in the same plot by default. rr.log( "trig/sin", - rr.SeriesPoint( - color=[255, 0, 0], - name="sin(0.01t)", - marker="circle", - marker_size=4, + rr.SeriesPoints( + colors=[255, 0, 0], + names="sin(0.01t)", + markers="circle", + marker_sizes=4, ), static=True, ) rr.log( "trig/cos", - rr.SeriesPoint( - color=[0, 255, 0], - name="cos(0.01t)", - marker="cross", - marker_size=2, + rr.SeriesPoints( + colors=[0, 255, 0], + names="cos(0.01t)", + markers="cross", + marker_sizes=2, ), static=True, ) + # Log the data on a timeline called "step". for t in range(int(tau * 2 * 10.0)): rr.set_time("step", sequence=t) - rr.log("trig/sin", rr.Scalar(sin(float(t) / 10.0))) - rr.log("trig/cos", rr.Scalar(cos(float(t) / 10.0))) + rr.log("trig/sin", rr.Scalars(sin(float(t) / 10.0))) + rr.log("trig/cos", rr.Scalars(cos(float(t) / 10.0))) diff --git a/docs/snippets/all/archetypes/series_point_style.rs b/docs/snippets/all/archetypes/series_points_style.rs similarity index 54% rename from docs/snippets/all/archetypes/series_point_style.rs rename to docs/snippets/all/archetypes/series_points_style.rs index 6843342c0b76..9ce5886b8ede 100644 --- a/docs/snippets/all/archetypes/series_point_style.rs +++ b/docs/snippets/all/archetypes/series_points_style.rs @@ -8,27 +8,27 @@ fn main() -> Result<(), Box> { // Log two point series under a shared root so that they show in the same plot by default. rec.log_static( "trig/sin", - &rerun::SeriesPoint::new() - .with_color([255, 0, 0]) - .with_name("sin(0.01t)") - .with_marker(rerun::components::MarkerShape::Circle) - .with_marker_size(4.0), + &rerun::SeriesPoints::new() + .with_colors([[255, 0, 0]]) + .with_names(["sin(0.01t)"]) + .with_markers([rerun::components::MarkerShape::Circle]) + .with_marker_sizes([4.0]), )?; rec.log_static( "trig/cos", - &rerun::SeriesPoint::new() - .with_color([0, 255, 0]) - .with_name("cos(0.01t)") - .with_marker(rerun::components::MarkerShape::Cross) - .with_marker_size(2.0), + &rerun::SeriesPoints::new() + .with_colors([[0, 255, 0]]) + .with_names(["cos(0.01t)"]) + .with_markers([rerun::components::MarkerShape::Cross]) + .with_marker_sizes([2.0]), )?; for t in 0..((std::f32::consts::TAU * 2.0 * 10.0) as i64) { rec.set_time_sequence("step", t); // Log two time series under a shared root so that they show in the same plot by default. - rec.log("trig/sin", &rerun::Scalar::new((t as f64 / 10.0).sin()))?; - rec.log("trig/cos", &rerun::Scalar::new((t as f64 / 10.0).cos()))?; + rec.log("trig/sin", &rerun::Scalars::one((t as f64 / 10.0).sin()))?; + rec.log("trig/cos", &rerun::Scalars::one((t as f64 / 10.0).cos()))?; } Ok(()) diff --git a/docs/snippets/all/tutorials/data_out.py b/docs/snippets/all/tutorials/data_out.py index e5ce92c8ecf9..8c47d695dfea 100644 --- a/docs/snippets/all/tutorials/data_out.py +++ b/docs/snippets/all/tutorials/data_out.py @@ -33,7 +33,7 @@ rr.send_columns( "/jaw_open_state", indexes=[rr.TimeColumn("frame_nr", sequence=df["frame_nr"])], - columns=rr.Scalar.columns(scalar=df["jawOpenState"]), + columns=rr.Scalars.columns(scalars=df["jawOpenState"]), ) # log a `Label` component to the face bounding box entity diff --git a/docs/snippets/all/tutorials/fixed_window_plot.py b/docs/snippets/all/tutorials/fixed_window_plot.py index c119d8f6bd2d..4a3546c2daa9 100644 --- a/docs/snippets/all/tutorials/fixed_window_plot.py +++ b/docs/snippets/all/tutorials/fixed_window_plot.py @@ -35,4 +35,4 @@ rr.set_time("time", timestamp=cur_time) - rr.log("random_walk", rr.Scalar(value)) + rr.log("random_walk", rr.Scalars(value)) diff --git a/docs/snippets/all/tutorials/visualizer-overrides.py b/docs/snippets/all/tutorials/visualizer-overrides.py index 90cf36d252f6..c79a2a178ca8 100644 --- a/docs/snippets/all/tutorials/visualizer-overrides.py +++ b/docs/snippets/all/tutorials/visualizer-overrides.py @@ -11,15 +11,15 @@ for t in range(int(tau * 2 * 10.0)): rr.set_time("step", sequence=t) - rr.log("trig/sin", rr.Scalar(sin(float(t) / 10.0))) - rr.log("trig/cos", rr.Scalar(cos(float(t) / 10.0))) + rr.log("trig/sin", rr.Scalars(sin(float(t) / 10.0))) + rr.log("trig/cos", rr.Scalars(cos(float(t) / 10.0))) -# Use the SeriesPoint visualizer for the sin series. +# Use the SeriesPoints visualizer for the sin series. rr.send_blueprint( rrb.TimeSeriesView( overrides={ "trig/sin": [ - rrb.VisualizerOverrides(rrb.visualizers.SeriesPoint), + rrb.VisualizerOverrides(rrb.visualizers.SeriesPoints), ], }, ), diff --git a/docs/snippets/all/views/dataframe.py b/docs/snippets/all/views/dataframe.py index c92794193405..88a266acc3e1 100644 --- a/docs/snippets/all/views/dataframe.py +++ b/docs/snippets/all/views/dataframe.py @@ -10,12 +10,12 @@ # Log some data. for t in range(int(math.pi * 4 * 100.0)): rr.set_time("t", duration=t) - rr.log("trig/sin", rr.Scalar(math.sin(float(t) / 100.0))) - rr.log("trig/cos", rr.Scalar(math.cos(float(t) / 100.0))) + rr.log("trig/sin", rr.Scalars(math.sin(float(t) / 100.0))) + rr.log("trig/cos", rr.Scalars(math.cos(float(t) / 100.0))) # some sparse data if t % 5 == 0: - rr.log("trig/tan_sparse", rr.Scalar(math.tan(float(t) / 100.0))) + rr.log("trig/tan_sparse", rr.Scalars(math.tan(float(t) / 100.0))) # Create a Dataframe View blueprint = rrb.Blueprint( diff --git a/docs/snippets/all/views/timeseries.py b/docs/snippets/all/views/timeseries.py index 36dda00eba73..34b34801b691 100644 --- a/docs/snippets/all/views/timeseries.py +++ b/docs/snippets/all/views/timeseries.py @@ -8,15 +8,15 @@ rr.init("rerun_example_timeseries", spawn=True) # Log some trigonometric functions -rr.log("trig/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)"), static=True) -rr.log("trig/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)"), static=True) -rr.log("trig/cos", rr.SeriesLine(color=[0, 0, 255], name="cos(0.01t) scaled"), static=True) +rr.log("trig/sin", rr.SeriesLines(colors=[255, 0, 0], names="sin(0.01t)"), static=True) +rr.log("trig/cos", rr.SeriesLines(colors=[0, 255, 0], names="cos(0.01t)"), static=True) +rr.log("trig/cos_scaled", rr.SeriesLines(colors=[0, 0, 255], names="cos(0.01t) scaled"), static=True) for t in range(int(math.pi * 4 * 100.0)): rr.set_time("timeline0", sequence=t) rr.set_time("timeline1", duration=t) - rr.log("trig/sin", rr.Scalar(math.sin(float(t) / 100.0))) - rr.log("trig/cos", rr.Scalar(math.cos(float(t) / 100.0))) - rr.log("trig/cos_scaled", rr.Scalar(math.cos(float(t) / 100.0) * 2.0)) + rr.log("trig/sin", rr.Scalars(math.sin(float(t) / 100.0))) + rr.log("trig/cos", rr.Scalars(math.cos(float(t) / 100.0))) + rr.log("trig/cos_scaled", rr.Scalars(math.cos(float(t) / 100.0) * 2.0)) # Create a TimeSeries View blueprint = rrb.Blueprint( diff --git a/docs/snippets/snippets.toml b/docs/snippets/snippets.toml index f904f86d92fd..6d4c13213260 100644 --- a/docs/snippets/snippets.toml +++ b/docs/snippets/snippets.toml @@ -74,6 +74,9 @@ features = [ ], ] + +# -------------------------------------------------------------------------------------------------- + # These entries won't run at all. # # NOTE: Non-runnable python snippets will have to also be added the `rerun_py/pyproject.toml` @@ -223,6 +226,8 @@ features = [ "rust", # Not implemented ] +# -------------------------------------------------------------------------------------------------- + # These entries will run but their results won't be compared to the baseline. # # You should only ever use this if the test cannot yet be implemented in a way that yields the right @@ -335,6 +340,25 @@ quick_start = [ # These examples don't have exactly the same implementation. "cpp", # somehow, C++ yields a different result, see ] +"archetypes/scalars_multiple_plots" = [ # TODO(#3235): Slight floating point differences + "cpp", + "py", + "rust", +] +"archetypes/series_lines_style" = [ # TODO(#3235): Slight floating point differences + "cpp", + "py", + "rust", +] +"archetypes/series_points_style" = [ # TODO(#3235): Slight floating point differences + "cpp", + "py", + "rust", +] + + +# ----------------------------------------------------------------------------- + # `$config_dir` will be replaced with the absolute path of `docs/snippets`. [extra_args] "archetypes/asset3d_simple" = ["$config_dir/../../tests/assets/cube.glb"] diff --git a/examples/cpp/stereo_vision_slam/README.md b/examples/cpp/stereo_vision_slam/README.md index ec814ef1c6c0..c624f03eda62 100644 --- a/examples/cpp/stereo_vision_slam/README.md +++ b/examples/cpp/stereo_vision_slam/README.md @@ -18,7 +18,7 @@ Visualizes stereo vision SLAM on the [KITTI dataset](https://www.cvlibs.net/data # Used Rerun types -[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`LineStrips3D`](https://rerun.io/docs/reference/types/archetypes/line_strips3d), [`Scalar`](https://rerun.io/docs/reference/types/archetypes/scalar), [`Transform3D`](https://rerun.io/docs/reference/types/archetypes/transform3d), [`Pinhole`](https://rerun.io/docs/reference/types/archetypes/pinhole), [`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d), [`TextLog`](https://rerun.io/docs/reference/types/archetypes/text_log) +[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`LineStrips3D`](https://rerun.io/docs/reference/types/archetypes/line_strips3d), [`Scalars`](https://rerun.io/docs/reference/types/archetypes/scalars?speculative-link), [`Transform3D`](https://rerun.io/docs/reference/types/archetypes/transform3d), [`Pinhole`](https://rerun.io/docs/reference/types/archetypes/pinhole), [`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d), [`TextLog`](https://rerun.io/docs/reference/types/archetypes/text_log) # Background @@ -141,7 +141,7 @@ void Viewer::Plot(std::string plot_name, double value, unsigned long maxkeyframe { // … rec.set_time_sequence("max_keyframe_id", maxkeyframe_id); - rec.log(plot_name, rerun::Scalar(value)); + rec.log(plot_name, rerun::Scalars(value)); } ``` diff --git a/examples/cpp/vrs/README.md b/examples/cpp/vrs/README.md index 31977c49dfe8..0c2f91b52182 100644 --- a/examples/cpp/vrs/README.md +++ b/examples/cpp/vrs/README.md @@ -18,7 +18,7 @@ This is an example that shows how to use Rerun's C++ API to log and view [VRS](h # Used Rerun types -[`Arrows3D`](https://www.rerun.io/docs/reference/types/archetypes/arrows3d), [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar), [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document) +[`Arrows3D`](https://www.rerun.io/docs/reference/types/archetypes/arrows3d), [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Scalars`](https://www.rerun.io/docs/reference/types/archetypes/scalars?speculative-link), [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document) # Background This C++ example demonstrates how to visualize VRS files with Rerun. @@ -40,25 +40,25 @@ void IMUPlayer::log_accelerometer(const std::array& accelMSec2) { ```cpp void IMUPlayer::log_accelerometer(const std::array& accelMSec2) { // … existing code for Arrows3D … - _rec->log(_entity_path + "/accelerometer/x", rerun::Scalar(accelMSec2[0])); - _rec->log(_entity_path + "/accelerometer/y", rerun::Scalar(accelMSec2[1])); - _rec->log(_entity_path + "/accelerometer/z", rerun::Scalar(accelMSec2[2])); + _rec->log(_entity_path + "/accelerometer/x", rerun::Scalars(accelMSec2[0])); + _rec->log(_entity_path + "/accelerometer/y", rerun::Scalars(accelMSec2[1])); + _rec->log(_entity_path + "/accelerometer/z", rerun::Scalars(accelMSec2[2])); } ``` ```cpp void IMUPlayer::log_gyroscope(const std::array& gyroRadSec) { - _rec->log(_entity_path + "/gyroscope/x", rerun::Scalar(gyroRadSec[0])); - _rec->log(_entity_path + "/gyroscope/y", rerun::Scalar(gyroRadSec[1])); - _rec->log(_entity_path + "/gyroscope/z", rerun::Scalar(gyroRadSec[2])); + _rec->log(_entity_path + "/gyroscope/x", rerun::Scalars(gyroRadSec[0])); + _rec->log(_entity_path + "/gyroscope/y", rerun::Scalars(gyroRadSec[1])); + _rec->log(_entity_path + "/gyroscope/z", rerun::Scalars(gyroRadSec[2])); } ``` ```cpp void IMUPlayer::log_magnetometer(const std::array& magTesla) { - _rec->log(_entity_path + "/magnetometer/x", rerun::Scalar(magTesla[0])); - _rec->log(_entity_path + "/magnetometer/y", rerun::Scalar(magTesla[1])); - _rec->log(_entity_path + "/magnetometer/z", rerun::Scalar(magTesla[2])); + _rec->log(_entity_path + "/magnetometer/x", rerun::Scalars(magTesla[0])); + _rec->log(_entity_path + "/magnetometer/y", rerun::Scalars(magTesla[1])); + _rec->log(_entity_path + "/magnetometer/z", rerun::Scalars(magTesla[2])); } ``` diff --git a/examples/python/air_traffic_data/air_traffic_data.py b/examples/python/air_traffic_data/air_traffic_data.py index b35beac25ab9..e344ae5a15be 100644 --- a/examples/python/air_traffic_data/air_traffic_data.py +++ b/examples/python/air_traffic_data/air_traffic_data.py @@ -270,8 +270,8 @@ def process_measurement(self, measurement: Measurement) -> None: if measurement.barometric_altitude is not None: rr.log( entity_path + "/barometric_altitude", - rr.Scalar(measurement.barometric_altitude), - rr.SeriesLine(color=color), + rr.Scalars(measurement.barometric_altitude), + rr.SeriesLines(colors=color), ) def flush(self) -> None: @@ -326,7 +326,7 @@ def log_position_and_altitude(self, df: polars.DataFrame, icao_id: str) -> None: # rr.GeoPoints.from_fields(colors=color), static=True, ) - rr.log(entity_path + "/barometric_altitude", rr.SeriesLine.from_fields(color=color), static=True) + rr.log(entity_path + "/barometric_altitude", rr.SeriesLines.from_fields(colors=color), static=True) self._position_indicators.add(icao_id) timestamps = rr.TimeColumn("unix_time", timestamp=df["timestamp"].to_numpy()) @@ -351,7 +351,7 @@ def log_position_and_altitude(self, df: polars.DataFrame, icao_id: str) -> None: rr.send_columns( entity_path + "/barometric_altitude", [timestamps], - rr.Scalar.columns(scalar=df["barometric_altitude"].to_numpy()), + rr.Scalars.columns(scalars=df["barometric_altitude"].to_numpy()), ) def log_ground_status(self, df: polars.DataFrame, icao_id: str) -> None: diff --git a/examples/python/blueprint_stocks/blueprint_stocks.py b/examples/python/blueprint_stocks/blueprint_stocks.py index d992bb43abc0..a6055aa02351 100755 --- a/examples/python/blueprint_stocks/blueprint_stocks.py +++ b/examples/python/blueprint_stocks/blueprint_stocks.py @@ -104,18 +104,18 @@ def hide_panels(viewport: rrb.ContainerLike) -> rrb.BlueprintLike: } -def style_plot(symbol: str) -> rr.SeriesLine: - return rr.SeriesLine( - color=brand_colors[symbol], - name=symbol, +def style_plot(symbol: str) -> rr.SeriesLines: + return rr.SeriesLines( + colors=brand_colors[symbol], + names=symbol, ) -def style_peak(symbol: str) -> rr.SeriesPoint: - return rr.SeriesPoint( - color=0xFF0000FF, - name=f"{symbol} (peak)", - marker="up", +def style_peak(symbol: str) -> rr.SeriesPoints: + return rr.SeriesPoints( + colors=0xFF0000FF, + names=f"{symbol} (peak)", + markers="up", ) @@ -210,9 +210,9 @@ def main() -> None: for row in hist.itertuples(): rr.set_time("time", duration=row.Index) - rr.log(f"stocks/{symbol}/{day}", rr.Scalar(row.High)) + rr.log(f"stocks/{symbol}/{day}", rr.Scalars(row.High)) if row.Index == peak: - rr.log(f"stocks/{symbol}/peaks/{day}", rr.Scalar(row.High)) + rr.log(f"stocks/{symbol}/peaks/{day}", rr.Scalars(row.High)) rr.script_teardown(args) diff --git a/examples/python/face_tracking/README.md b/examples/python/face_tracking/README.md index 0506e53ef24b..ca0b76ff5079 100644 --- a/examples/python/face_tracking/README.md +++ b/examples/python/face_tracking/README.md @@ -17,7 +17,7 @@ Use the [MediaPipe](https://github.com/google-ai-edge/mediapipe) Face Detector a ## Used Rerun types -[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Points2D`](https://www.rerun.io/docs/reference/types/archetypes/points2d), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`Boxes2D`](https://www.rerun.io/docs/reference/types/archetypes/boxes2d), [`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context), [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar) +[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Points2D`](https://www.rerun.io/docs/reference/types/archetypes/points2d), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`Boxes2D`](https://www.rerun.io/docs/reference/types/archetypes/boxes2d), [`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context), [`Scalars`](https://www.rerun.io/docs/reference/types/archetypes/scalars?speculative-link) ## Background The face and face landmark detection technology aims to give the ability of the devices to interpret face movements and facial expressions as commands or inputs. @@ -159,14 +159,14 @@ rr.log( ) ``` -### Scalar +### Scalars Blendshapes are essentially predefined facial expressions or configurations that can be detected by the face landmark detection model. Each blendshape typically corresponds to a specific facial movement or expression, such as blinking, squinting, smiling, etc. The blendshapes are logged along with their corresponding scores. ```python for blendshape in blendshapes: if blendshape.category_name in BLENDSHAPES_CATEGORIES: - rr.log(f"blendshapes/{i}/{blendshape.category_name}", rr.Scalar(blendshape.score)) + rr.log(f"blendshapes/{i}/{blendshape.category_name}", rr.Scalars(blendshape.score)) ``` ## Run the code diff --git a/examples/python/face_tracking/face_tracking.py b/examples/python/face_tracking/face_tracking.py index d764dda937a3..9ce1188bf341 100755 --- a/examples/python/face_tracking/face_tracking.py +++ b/examples/python/face_tracking/face_tracking.py @@ -311,7 +311,7 @@ def is_empty(i: Iterator[Any]) -> bool: # NOTE(cmc): That one we still log as temporal, otherwise it's really meh. rr.log( f"blendshapes/{i}/{blendshape.category_name}", - rr.Scalar(blendshape.score), + rr.Scalars(blendshape.score), ) diff --git a/examples/python/imu_signals/README.md b/examples/python/imu_signals/README.md index 67a35d0dbd3b..f3aa8ffb4eab 100644 --- a/examples/python/imu_signals/README.md +++ b/examples/python/imu_signals/README.md @@ -38,11 +38,11 @@ times = rr.TimeColumn("timestamp", timestamp=imu_data["timestamp"]) # Extract gyroscope data (x, y, z axes) and log it to a single entity. gyro = imu_data[["gyro.x", "gyro.y", "gyro.z"]] -rr.send_columns("/gyroscope", indexes=[times], columns=rr.Scalar.columns(scalar=gyro)) +rr.send_columns("/gyroscope", indexes=[times], columns=rr.Scalars.columns(scalars=gyro)) # Extract accelerometer data (x, y, z axes) and log it to a single entity. accel = imu_data[["accel.x", "accel.y", "accel.z"]] -rr.send_columns("/accelerometer", indexes=[times], columns=rr.Scalar.columns(scalar=accel)) +rr.send_columns("/accelerometer", indexes=[times], columns=rr.Scalars.columns(scalars=accel)) ``` ## Running diff --git a/examples/python/imu_signals/imu_signals.py b/examples/python/imu_signals/imu_signals.py index e6d4755a563d..fca8bf7f5e92 100644 --- a/examples/python/imu_signals/imu_signals.py +++ b/examples/python/imu_signals/imu_signals.py @@ -42,7 +42,7 @@ def main() -> None: name="Gyroscope", overrides={ # TODO(#9022): Pluralize series line type. - "/gyroscope": rr.SeriesLine.from_fields(name=XYZ_AXIS_NAMES, color=XYZ_AXIS_COLORS), # type: ignore[arg-type] + "/gyroscope": rr.SeriesLines.from_fields(names=XYZ_AXIS_NAMES, colors=XYZ_AXIS_COLORS), # type: ignore[arg-type] }, ), rrb.TimeSeriesView( @@ -50,7 +50,7 @@ def main() -> None: name="Accelerometer", overrides={ # TODO(#9022): Pluralize series line type. - "/accelerometer": rr.SeriesLine.from_fields(name=XYZ_AXIS_NAMES, color=XYZ_AXIS_COLORS), # type: ignore[arg-type] + "/accelerometer": rr.SeriesLines.from_fields(names=XYZ_AXIS_NAMES, colors=XYZ_AXIS_COLORS), # type: ignore[arg-type] }, ), ), @@ -105,10 +105,10 @@ def _log_imu_data(max_time_sec: float) -> None: times = rr.TimeColumn("timestamp", timestamp=timestamps) gyro = selected[["gyro.x", "gyro.y", "gyro.z"]].to_numpy() - rr.send_columns("/gyroscope", indexes=[times], columns=rr.Scalar.columns(scalar=gyro)) + rr.send_columns("/gyroscope", indexes=[times], columns=rr.Scalars.columns(scalars=gyro)) accel = selected[["accel.x", "accel.y", "accel.z"]] - rr.send_columns("/accelerometer", indexes=[times], columns=rr.Scalar.columns(scalar=accel)) + rr.send_columns("/accelerometer", indexes=[times], columns=rr.Scalars.columns(scalars=accel)) def _log_image_data(max_time_sec: float) -> None: diff --git a/examples/python/live_scrolling_plot/README.md b/examples/python/live_scrolling_plot/README.md index d6e2f80c861e..97b2707f9bad 100644 --- a/examples/python/live_scrolling_plot/README.md +++ b/examples/python/live_scrolling_plot/README.md @@ -16,7 +16,7 @@ Visualize a live stream of several plots, scrolling horizontally to keep a fixed ## Used Rerun types -[`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar) +[`Scalars`](https://www.rerun.io/docs/reference/types/archetypes/scalars?speculative-link) ## Setting up the blueprint diff --git a/examples/python/live_scrolling_plot/live_scrolling_plot.py b/examples/python/live_scrolling_plot/live_scrolling_plot.py index 8f23fef7c0ab..be54d103459e 100644 --- a/examples/python/live_scrolling_plot/live_scrolling_plot.py +++ b/examples/python/live_scrolling_plot/live_scrolling_plot.py @@ -78,7 +78,7 @@ def main() -> None: # Output each series based on its generator for plot_idx, plot_path in enumerate(plot_paths): for series_idx, series_path in enumerate(series_paths): - rr.log(f"{plot_path}/{series_path}", rr.Scalar(next(values[plot_idx][series_idx]))) + rr.log(f"{plot_path}/{series_path}", rr.Scalars(next(values[plot_idx][series_idx]))) rr.script_teardown(args) diff --git a/examples/python/notebook_neural_field_2d/neural_field_2d.ipynb b/examples/python/notebook_neural_field_2d/neural_field_2d.ipynb index 52dc623c39a3..d223acee6bff 100644 --- a/examples/python/notebook_neural_field_2d/neural_field_2d.ipynb +++ b/examples/python/notebook_neural_field_2d/neural_field_2d.ipynb @@ -1,261 +1,261 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "b31c0a84", - "metadata": {}, - "source": [ - "## Imports and initialization" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1076c3a0", - "metadata": {}, - "outputs": [], - "source": [ - "from __future__ import annotations\n", - "\n", - "import io\n", - "import itertools\n", - "\n", - "import numpy as np\n", - "import PIL.Image\n", - "import requests\n", - "import rerun as rr # pip install rerun-sdk\n", - "import rerun.blueprint as rrb\n", - "import torch" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "bf894a1f", - "metadata": {}, - "source": [ - "## Define neural field class\n", - "\n", - "First, we define the neural field class which we can be used to represent any continuous ND signal. I.e., it maps an ND point to another ND point. In this notebook we fit fields to map from 2D image coordinates to RGB colors. This way the network weights can be interpreted as encoding a continuous image." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f709925e", - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "class NeuralField(torch.nn.Module):\n", - " \"\"\"Simple neural field composed of positional encoding, MLP, and activation function.\"\"\"\n", - "\n", - " def __init__(\n", - " self,\n", - " num_layers: int,\n", - " dim_hidden: int,\n", - " dim_in: int = 2,\n", - " dim_out: int = 3,\n", - " activation: str = \"sigmoid\",\n", - " pe_sigma: float | None = None,\n", - " ) -> None:\n", - " super().__init__()\n", - "\n", - " self.num_layers = num_layers\n", - " self.dim_hidden = dim_hidden\n", - " self.dim_in = dim_in\n", - " self.dim_out = dim_out\n", - " self.activation = activation\n", - " self.pe_sigma = pe_sigma\n", - "\n", - " sizes = [dim_in] + [dim_hidden for _ in range(num_layers - 1)] + [dim_out]\n", - " self.linears = torch.nn.ModuleList()\n", - " for in_size, out_size in zip(sizes[:-1], sizes[1:]):\n", - " self.linears.append(torch.nn.Linear(in_size, out_size))\n", - "\n", - " if self.pe_sigma is not None:\n", - " torch.nn.init.normal_(self.linears[0].weight, 0.0, self.pe_sigma)\n", - "\n", - " def __str__(self) -> str:\n", - " return f\"{self.num_layers} lay., {self.dim_hidden} neu., pe σ: {self.pe_sigma}\"\n", - "\n", - " def forward(self, input_points: torch.Tensor) -> torch.Tensor:\n", - " \"\"\"\n", - " Compute output for given input points.\n", - "\n", - " Args:\n", - " input_points: input points\n", - "\n", - " \"\"\"\n", - " if self.pe_sigma is None:\n", - " out = torch.relu(self.linears[0](input_points))\n", - " else:\n", - " out = torch.sin(self.linears[0](input_points))\n", - "\n", - " for linear in self.linears[1:-1]:\n", - " out = torch.relu(linear(out))\n", - "\n", - " out = self.linears[-1](out)\n", - "\n", - " if self.activation == \"sigmoid\":\n", - " out = torch.sigmoid(out)\n", - "\n", - " return out" - ] - }, - { - "cell_type": "markdown", - "id": "04c095ef", - "metadata": {}, - "source": [ - "## Initialize and visualize neural fields\n", - "\n", - "Now we create a few neural fields with different parameters and visualize their output as images. We assume that images are fit in a 0 to 1 unit square, so we query in a dense grid (with some additional margin to observe out-of-training behavior) to retrieve the image from the network. Note that the positional encoding encodes how quickly the neural field varies out-of-the-box. This corresponds to the amount of detail that the field can easily represent, but also determines how the field extrapolates outside of the training region." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "332d8d35-42f7-415a-b58b-9c55430cb67f", - "metadata": {}, - "outputs": [], - "source": [ - "fields = [\n", - " NeuralField(num_layers=5, dim_hidden=128, pe_sigma=5),\n", - " NeuralField(num_layers=5, dim_hidden=128, pe_sigma=15),\n", - " NeuralField(num_layers=5, dim_hidden=128, pe_sigma=30),\n", - " NeuralField(num_layers=5, dim_hidden=128, pe_sigma=100),\n", - "]\n", - "total_iterations = [0 for _ in fields]\n", - "\n", - "rr.init(\"rerun_example_cube\")\n", - "\n", - "blueprint = rrb.Blueprint(\n", - " rrb.Vertical(\n", - " rrb.Grid(\n", - " rrb.Spatial2DView(name=\"Target\", origin=\"target\"),\n", - " *[rrb.Spatial2DView(name=str(field), origin=f\"field_{i}\") for i, field in enumerate(fields)],\n", - " ),\n", - " rrb.TimeSeriesView(\n", - " name=\"Losses\",\n", - " origin=\"/\",\n", - " defaults=[rr.components.AggregationPolicyBatch(\"average\")],\n", - " plot_legend=rrb.Corner2D.LeftTop,\n", - " ),\n", - " row_shares=[0.7, 0.3],\n", - " ),\n", - " collapse_panels=True,\n", - ")\n", - "for i, field in enumerate(fields):\n", - " rr.log(f\"loss/field_{i}\", rr.SeriesLine(name=str(field)), static=True)\n", - "\n", - "rr.notebook_show(blueprint=blueprint, width=1050, height=600)\n", - "\n", - "\n", - "@torch.no_grad()\n", - "def log_field_as_image(\n", - " entity_path: str,\n", - " field: NeuralField,\n", - " min_uv: tuple[float],\n", - " max_uv: tuple[float],\n", - " uv_resolution: tuple[int],\n", - ") -> None:\n", - " u_values = torch.linspace(min_uv[0], max_uv[0], uv_resolution[0])\n", - " v_values = torch.linspace(min_uv[1], max_uv[1], uv_resolution[1])\n", - " uv_points = torch.cartesian_prod(u_values, v_values) + 0.5 / torch.tensor(\n", - " uv_resolution,\n", - " ) # 0.5 is the center of a pixel\n", - " predictions = field(uv_points)\n", - " image_prediction = torch.clamp(predictions.reshape(uv_resolution[0], uv_resolution[1], 3), 0, 1)\n", - " image_prediction = image_prediction.permute(1, 0, 2)\n", - " rr.log(entity_path, rr.Image(image_prediction.numpy(force=True)))\n", - "\n", - "\n", - "rr.set_time_sequence(\"iteration\", 0)\n", - "for i, field in enumerate(fields):\n", - " log_field_as_image(f\"field_{i}\", field, (-0.1, -0.1), (1.1, 1.1), (100, 100))" - ] - }, - { - "cell_type": "markdown", - "id": "649b8e80-e69d-4b6b-be51-50cbf4c20495", - "metadata": {}, - "source": [ - "## Train neural field\n", - "\n", - "Now we train the neural fields for a fixed number of iterations. If you run the cell twice, we continue training where we left off. To reset the fields, run the previous cell again." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "19545879-9f90-489d-9b50-27fa485a5888", - "metadata": {}, - "outputs": [], - "source": [ - "field_ids = [0, 1, 2, 3] # if you only want to train one of the fields\n", - "num_iterations = 10000\n", - "batch_size = 1000\n", - "learning_rate = 1e-3\n", - "log_image_period = 10\n", - "\n", - "\n", - "response = requests.get(\"https://storage.googleapis.com/rerun-example-datasets/example_images/tiger.jpg\")\n", - "# response = requests.get(\"https://storage.googleapis.com/rerun-example-datasets/example_images/bird.jpg\")\n", - "target_image = torch.from_numpy(np.asarray(PIL.Image.open(io.BytesIO(response.content)))).float() / 255\n", - "\n", - "rr.log(\"target\", rr.Image(target_image))\n", - "\n", - "try:\n", - " parameters = itertools.chain(*[fields[field_id].parameters() for field_id in field_ids])\n", - " optimizer = torch.optim.Adam(parameters, lr=learning_rate)\n", - " for iteration in range(num_iterations):\n", - " optimizer.zero_grad()\n", - "\n", - " target_uvs = torch.rand(batch_size, 2)\n", - " target_jis = (target_uvs * torch.tensor([target_image.shape[1], target_image.shape[0]])).int()\n", - " target_rgbs = target_image[target_jis[:, 1], target_jis[:, 0]]\n", - " for field_id in field_ids:\n", - " field = fields[field_id]\n", - " total_iterations[field_id] += 1\n", - "\n", - " predicted_rgbs = field(target_uvs)\n", - " loss = torch.nn.functional.mse_loss(target_rgbs, predicted_rgbs)\n", - "\n", - " rr.set_time_sequence(\"iteration\", total_iterations[field_id])\n", - " rr.log(f\"loss/field_{field_id}\", rr.Scalar(loss.item()))\n", - " loss.backward()\n", - "\n", - " optimizer.step()\n", - "\n", - " if iteration % log_image_period == 0:\n", - " for field_id in field_ids:\n", - " log_field_as_image(f\"field_{field_id}\", fields[field_id], (-0.1, -0.1), (1.1, 1.1), (100, 100))\n", - "except KeyboardInterrupt:\n", - " print(\"Training stopped.\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.9" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "cells": [ + { + "cell_type": "markdown", + "id": "b31c0a84", + "metadata": {}, + "source": [ + "## Imports and initialization" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1076c3a0", + "metadata": {}, + "outputs": [], + "source": [ + "from __future__ import annotations\n", + "\n", + "import io\n", + "import itertools\n", + "\n", + "import numpy as np\n", + "import PIL.Image\n", + "import requests\n", + "import rerun as rr # pip install rerun-sdk\n", + "import rerun.blueprint as rrb\n", + "import torch" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "bf894a1f", + "metadata": {}, + "source": [ + "## Define neural field class\n", + "\n", + "First, we define the neural field class which we can be used to represent any continuous ND signal. I.e., it maps an ND point to another ND point. In this notebook we fit fields to map from 2D image coordinates to RGB colors. This way the network weights can be interpreted as encoding a continuous image." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f709925e", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "class NeuralField(torch.nn.Module):\n", + " \"\"\"Simple neural field composed of positional encoding, MLP, and activation function.\"\"\"\n", + "\n", + " def __init__(\n", + " self,\n", + " num_layers: int,\n", + " dim_hidden: int,\n", + " dim_in: int = 2,\n", + " dim_out: int = 3,\n", + " activation: str = \"sigmoid\",\n", + " pe_sigma: float | None = None,\n", + " ) -> None:\n", + " super().__init__()\n", + "\n", + " self.num_layers = num_layers\n", + " self.dim_hidden = dim_hidden\n", + " self.dim_in = dim_in\n", + " self.dim_out = dim_out\n", + " self.activation = activation\n", + " self.pe_sigma = pe_sigma\n", + "\n", + " sizes = [dim_in] + [dim_hidden for _ in range(num_layers - 1)] + [dim_out]\n", + " self.linears = torch.nn.ModuleList()\n", + " for in_size, out_size in zip(sizes[:-1], sizes[1:]):\n", + " self.linears.append(torch.nn.Linear(in_size, out_size))\n", + "\n", + " if self.pe_sigma is not None:\n", + " torch.nn.init.normal_(self.linears[0].weight, 0.0, self.pe_sigma)\n", + "\n", + " def __str__(self) -> str:\n", + " return f\"{self.num_layers} lay., {self.dim_hidden} neu., pe σ: {self.pe_sigma}\"\n", + "\n", + " def forward(self, input_points: torch.Tensor) -> torch.Tensor:\n", + " \"\"\"\n", + " Compute output for given input points.\n", + "\n", + " Args:\n", + " input_points: input points\n", + "\n", + " \"\"\"\n", + " if self.pe_sigma is None:\n", + " out = torch.relu(self.linears[0](input_points))\n", + " else:\n", + " out = torch.sin(self.linears[0](input_points))\n", + "\n", + " for linear in self.linears[1:-1]:\n", + " out = torch.relu(linear(out))\n", + "\n", + " out = self.linears[-1](out)\n", + "\n", + " if self.activation == \"sigmoid\":\n", + " out = torch.sigmoid(out)\n", + "\n", + " return out" + ] + }, + { + "cell_type": "markdown", + "id": "04c095ef", + "metadata": {}, + "source": [ + "## Initialize and visualize neural fields\n", + "\n", + "Now we create a few neural fields with different parameters and visualize their output as images. We assume that images are fit in a 0 to 1 unit square, so we query in a dense grid (with some additional margin to observe out-of-training behavior) to retrieve the image from the network. Note that the positional encoding encodes how quickly the neural field varies out-of-the-box. This corresponds to the amount of detail that the field can easily represent, but also determines how the field extrapolates outside of the training region." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "332d8d35-42f7-415a-b58b-9c55430cb67f", + "metadata": {}, + "outputs": [], + "source": [ + "fields = [\n", + " NeuralField(num_layers=5, dim_hidden=128, pe_sigma=5),\n", + " NeuralField(num_layers=5, dim_hidden=128, pe_sigma=15),\n", + " NeuralField(num_layers=5, dim_hidden=128, pe_sigma=30),\n", + " NeuralField(num_layers=5, dim_hidden=128, pe_sigma=100),\n", + "]\n", + "total_iterations = [0 for _ in fields]\n", + "\n", + "rr.init(\"rerun_example_cube\")\n", + "\n", + "blueprint = rrb.Blueprint(\n", + " rrb.Vertical(\n", + " rrb.Grid(\n", + " rrb.Spatial2DView(name=\"Target\", origin=\"target\"),\n", + " *[rrb.Spatial2DView(name=str(field), origin=f\"field_{i}\") for i, field in enumerate(fields)],\n", + " ),\n", + " rrb.TimeSeriesView(\n", + " name=\"Losses\",\n", + " origin=\"/\",\n", + " defaults=[rr.components.AggregationPolicyBatch(\"average\")],\n", + " plot_legend=rrb.Corner2D.LeftTop,\n", + " ),\n", + " row_shares=[0.7, 0.3],\n", + " ),\n", + " collapse_panels=True,\n", + ")\n", + "for i, field in enumerate(fields):\n", + " rr.log(f\"loss/field_{i}\", rr.SeriesLines(name=str(field)), static=True)\n", + "\n", + "rr.notebook_show(blueprint=blueprint, width=1050, height=600)\n", + "\n", + "\n", + "@torch.no_grad()\n", + "def log_field_as_image(\n", + " entity_path: str,\n", + " field: NeuralField,\n", + " min_uv: tuple[float],\n", + " max_uv: tuple[float],\n", + " uv_resolution: tuple[int],\n", + ") -> None:\n", + " u_values = torch.linspace(min_uv[0], max_uv[0], uv_resolution[0])\n", + " v_values = torch.linspace(min_uv[1], max_uv[1], uv_resolution[1])\n", + " uv_points = torch.cartesian_prod(u_values, v_values) + 0.5 / torch.tensor(\n", + " uv_resolution,\n", + " ) # 0.5 is the center of a pixel\n", + " predictions = field(uv_points)\n", + " image_prediction = torch.clamp(predictions.reshape(uv_resolution[0], uv_resolution[1], 3), 0, 1)\n", + " image_prediction = image_prediction.permute(1, 0, 2)\n", + " rr.log(entity_path, rr.Image(image_prediction.numpy(force=True)))\n", + "\n", + "\n", + "rr.set_time_sequence(\"iteration\", 0)\n", + "for i, field in enumerate(fields):\n", + " log_field_as_image(f\"field_{i}\", field, (-0.1, -0.1), (1.1, 1.1), (100, 100))" + ] + }, + { + "cell_type": "markdown", + "id": "649b8e80-e69d-4b6b-be51-50cbf4c20495", + "metadata": {}, + "source": [ + "## Train neural field\n", + "\n", + "Now we train the neural fields for a fixed number of iterations. If you run the cell twice, we continue training where we left off. To reset the fields, run the previous cell again." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "19545879-9f90-489d-9b50-27fa485a5888", + "metadata": {}, + "outputs": [], + "source": [ + "field_ids = [0, 1, 2, 3] # if you only want to train one of the fields\n", + "num_iterations = 10000\n", + "batch_size = 1000\n", + "learning_rate = 1e-3\n", + "log_image_period = 10\n", + "\n", + "\n", + "response = requests.get(\"https://storage.googleapis.com/rerun-example-datasets/example_images/tiger.jpg\")\n", + "# response = requests.get(\"https://storage.googleapis.com/rerun-example-datasets/example_images/bird.jpg\")\n", + "target_image = torch.from_numpy(np.asarray(PIL.Image.open(io.BytesIO(response.content)))).float() / 255\n", + "\n", + "rr.log(\"target\", rr.Image(target_image))\n", + "\n", + "try:\n", + " parameters = itertools.chain(*[fields[field_id].parameters() for field_id in field_ids])\n", + " optimizer = torch.optim.Adam(parameters, lr=learning_rate)\n", + " for iteration in range(num_iterations):\n", + " optimizer.zero_grad()\n", + "\n", + " target_uvs = torch.rand(batch_size, 2)\n", + " target_jis = (target_uvs * torch.tensor([target_image.shape[1], target_image.shape[0]])).int()\n", + " target_rgbs = target_image[target_jis[:, 1], target_jis[:, 0]]\n", + " for field_id in field_ids:\n", + " field = fields[field_id]\n", + " total_iterations[field_id] += 1\n", + "\n", + " predicted_rgbs = field(target_uvs)\n", + " loss = torch.nn.functional.mse_loss(target_rgbs, predicted_rgbs)\n", + "\n", + " rr.set_time_sequence(\"iteration\", total_iterations[field_id])\n", + " rr.log(f\"loss/field_{field_id}\", rr.Scalars(loss.item()))\n", + " loss.backward()\n", + "\n", + " optimizer.step()\n", + "\n", + " if iteration % log_image_period == 0:\n", + " for field_id in field_ids:\n", + " log_field_as_image(f\"field_{field_id}\", fields[field_id], (-0.1, -0.1), (1.1, 1.1), (100, 100))\n", + "except KeyboardInterrupt:\n", + " print(\"Training stopped.\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/examples/python/plots/README.md b/examples/python/plots/README.md index cf7e416dafe8..dd0bfb313e7d 100644 --- a/examples/python/plots/README.md +++ b/examples/python/plots/README.md @@ -18,7 +18,7 @@ This example demonstrates how to log simple plots with the Rerun SDK. Charts can ## Used Rerun types -[`BarChart`](https://www.rerun.io/docs/reference/types/archetypes/bar_chart), [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar), [`SeriesPoint`](https://www.rerun.io/docs/reference/types/archetypes/series_point), [`SeriesLine`](https://www.rerun.io/docs/reference/types/archetypes/series_line), [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document) +[`BarChart`](https://www.rerun.io/docs/reference/types/archetypes/bar_chart), [`Scalars`](https://www.rerun.io/docs/reference/types/archetypes/scalars?speculative-link), [`SeriesPoints`](https://www.rerun.io/docs/reference/types/archetypes/series_points?speculative-link), [`SeriesLines`](https://www.rerun.io/docs/reference/types/archetypes/series_lines?speculative-link), [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document) ## Logging and visualizing with Rerun @@ -26,10 +26,10 @@ This example shows various plot types that you can create using Rerun. Common us losses or metrics over time, histograms, or general function plots. The bar chart is created by logging the [`BarChart`](https://www.rerun.io/docs/reference/types/archetypes/bar_chart) archetype. -All other plots are created using the [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar) archetype. +All other plots are created using the [`Scalars`](https://www.rerun.io/docs/reference/types/archetypes/scalars?speculative-link) archetype. Each plot is created by logging scalars at different time steps (i.e., the x-axis). -Additionally, the plots are styled using the [`SeriesLine`](https://www.rerun.io/docs/reference/types/archetypes/series_line) and -[`SeriesPoint`](https://www.rerun.io/docs/reference/types/archetypes/series_point) archetypes respectively. +Additionally, the plots are styled using the [`SeriesLines`](https://www.rerun.io/docs/reference/types/archetypes/series_lines?speculative-link) and +[`SeriesPoints`](https://www.rerun.io/docs/reference/types/archetypes/series_poins?speculative-linkt) archetypes respectively. The visualizations in this example were created with the following Rerun code: @@ -46,13 +46,13 @@ def log_bar_chart() -> None: ### Curves The `log_parabola` function logs a parabola curve (sine and cosine functions) as a time series. -It first sets up a time sequence using [`timelines`](https://www.rerun.io/docs/concepts/timelines), then calculates the y-value of the parabola at each time step, and logs it using [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar) archetype. -It also adjusts the width and color of the plotted line based on the calculated y value using [`SeriesLine`](https://www.rerun.io/docs/reference/types/archetypes/series_line) archetype. +It first sets up a time sequence using [`timelines`](https://www.rerun.io/docs/concepts/timelines), then calculates the y-value of the parabola at each time step, and logs it using [`Scalars`](https://www.rerun.io/docs/reference/types/archetypes/scalars?speculative-link) archetype. +It also adjusts the width and color of the plotted line based on the calculated y value using [`SeriesLines`](https://www.rerun.io/docs/reference/types/archetypes/series_lines?speculative-link) archetype. ```python def log_parabola() -> None: # Name never changes, log it only once. - rr.log("curves/parabola", rr.SeriesLine(name="f(t) = (0.01t - 3)³ + 1"), static=True) + rr.log("curves/parabola", rr.SeriesLines(name="f(t) = (0.01t - 3)³ + 1"), static=True) # Log a parabola as a time series for t in range(0, 1000, 10): @@ -62,8 +62,8 @@ def log_parabola() -> None: rr.log( "curves/parabola", - rr.Scalar(f_of_t), - rr.SeriesLine(width=width, color=color), + rr.Scalars(f_of_t), + rr.SeriesLines(width=width, color=color), ) ``` @@ -71,46 +71,46 @@ def log_parabola() -> None: The `log_trig` function logs sin and cos functions as time series. Sin and cos are logged with the same parent entity (i.e.,`trig/{cos,sin}`) which will put them in the same view by default. -It first logs the styling properties of the sin and cos plots using [`SeriesLine`](https://www.rerun.io/docs/reference/types/archetypes/series_line) archetype. -Then, it iterates over a range of time steps, calculates the sin and cos values at each time step, and logs them using [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar) archetype. +It first logs the styling properties of the sin and cos plots using [`SeriesLines`](https://www.rerun.io/docs/reference/types/archetypes/series_lines?speculative-link) archetype. +Then, it iterates over a range of time steps, calculates the sin and cos values at each time step, and logs them using [`Scalars`](https://www.rerun.io/docs/reference/types/archetypes/scalars?speculative-link) archetype. ```python def log_trig() -> None: # Styling doesn't change over time, log it once with static=True. - rr.log("trig/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)"), static=True) - rr.log("trig/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)"), static=True) + rr.log("trig/sin", rr.SeriesLines(color=[255, 0, 0], name="sin(0.01t)"), static=True) + rr.log("trig/cos", rr.SeriesLines(color=[0, 255, 0], name="cos(0.01t)"), static=True) for t in range(0, int(tau * 2 * 100.0)): rr.set_time("frame_nr", sequence=t) sin_of_t = sin(float(t) / 100.0) - rr.log("trig/sin", rr.Scalar(sin_of_t)) + rr.log("trig/sin", rr.Scalars(sin_of_t)) cos_of_t = cos(float(t) / 100.0) - rr.log("trig/cos", rr.Scalar(cos_of_t)) + rr.log("trig/cos", rr.Scalars(cos_of_t)) ``` ### Classification The `log_classification` function simulates a classification problem by logging a line function and randomly generated samples around that line. -It first logs the styling properties of the line plot using [`SeriesLine`](https://www.rerun.io/docs/reference/types/archetypes/series_line) archetype. -Then, it iterates over a range of time steps, calculates the y value of the line function at each time step, and logs it as a scalar using [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar) archetype. -Additionally, it generates random samples around the line function and logs them using [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar) and [`SeriesPoint`](https://www.rerun.io/docs/reference/types/archetypes/series_point) archetypes. +It first logs the styling properties of the line plot using [`SeriesLines`](https://www.rerun.io/docs/reference/types/archetypes/series_lines?speculative-link) archetype. +Then, it iterates over a range of time steps, calculates the y value of the line function at each time step, and logs it as a scalars using [`Scalars`](https://www.rerun.io/docs/reference/types/archetypes/scalars?speculative-link) archetype. +Additionally, it generates random samples around the line function and logs them using [`Scalars`](https://www.rerun.io/docs/reference/types/archetypes/scalars?speculative-link) and [`SeriesPoints`](https://www.rerun.io/docs/reference/types/archetypes/series_poins?speculative-linkt) archetypes. ```python def log_classification() -> None: # Log components that don't change only once: - rr.log("classification/line", rr.SeriesLine(color=[255, 255, 0], width=3.0), static=True) + rr.log("classification/line", rr.SeriesLines(colors=[255, 255, 0], widths=3.0), static=True) for t in range(0, 1000, 2): rr.set_time("frame_nr", sequence=t) # … existing code … - rr.log("classification/line", rr.Scalar(f_of_t)) + rr.log("classification/line", rr.Scalars(f_of_t)) # … existing code … - rr.log("classification/samples", rr.Scalar(g_of_t), rr.SeriesPoint(color=color, marker_size=marker_size)) + rr.log("classification/samples", rr.Scalars(g_of_t), rr.SeriesPoints(colors=color, marker_sizes=marker_size)) ``` @@ -138,4 +138,4 @@ python -m plots --help ## Advanced time series - [`send_columns`](https://ref.rerun.io/docs/python/stable/common/columnar_api/#rerun.send_columns) Logging many scalars individually can be slow. The [`send_columns`](https://ref.rerun.io/docs/python/stable/common/columnar_api/#rerun.send_columns) API can be used to log many scalars at once. -Check the [`Scalar` `send_columns` snippet](https://rerun.io/docs/reference/types/archetypes/scalar#scalar-send-columns) to learn more. +Check the [`Scalars` `send_columns` snippet](https://rerun.io/docs/reference/types/archetypes/scalars?speculative-links#scalars-send-columns) to learn more. diff --git a/examples/python/plots/plots.py b/examples/python/plots/plots.py index 30f22c70c84d..c3249416aef6 100755 --- a/examples/python/plots/plots.py +++ b/examples/python/plots/plots.py @@ -40,10 +40,10 @@ def log_bar_chart() -> None: def log_parabola() -> None: # Time-independent styling can be achieved by logging static components to the data store. Here, by using the - # `SeriesLine` archetype, we further hint the viewer to use the line plot visualizer. + # `SeriesLines` archetype, we further hint the viewer to use the line plot visualizer. # Alternatively, you can achieve time-independent styling using overrides, as is everywhere else in this example # (see the `main()` function). - rr.log("curves/parabola", rr.SeriesLine(name="f(t) = (0.01t - 3)³ + 1"), static=True) + rr.log("curves/parabola", rr.SeriesLines(names="f(t) = (0.01t - 3)³ + 1"), static=True) # Log a parabola as a time series for t in range(0, 1000, 10): @@ -57,11 +57,11 @@ def log_parabola() -> None: elif f_of_t > 10.0: color = [0, 255, 0] - # Note: by using the `rr.SeriesLine` archetype, we hint the viewer to use the line plot visualizer. + # Note: by using the `rr.SeriesLines` archetype, we hint the viewer to use the line plot visualizer. rr.log( "curves/parabola", - rr.Scalar(f_of_t), - rr.SeriesLine(width=width, color=color), + rr.Scalars(f_of_t), + rr.SeriesLines(widths=width, colors=color), ) @@ -70,10 +70,10 @@ def log_trig() -> None: rr.set_time("frame_nr", sequence=t) sin_of_t = sin(float(t) / 100.0) - rr.log("trig/sin", rr.Scalar(sin_of_t)) + rr.log("trig/sin", rr.Scalars(sin_of_t)) cos_of_t = cos(float(t) / 100.0) - rr.log("trig/cos", rr.Scalar(cos_of_t)) + rr.log("trig/cos", rr.Scalars(cos_of_t)) def log_spiral() -> None: @@ -88,7 +88,7 @@ def log_spiral() -> None: rr.send_columns( "spiral", indexes=[rr.TimeColumn("frame_nr", sequence=times)], - columns=[*rr.Scalar.columns(scalar=scalars)], + columns=[*rr.Scalars.columns(scalars=scalars)], ) @@ -97,7 +97,7 @@ def log_classification() -> None: rr.set_time("frame_nr", sequence=t) f_of_t = (2 * 0.01 * t) + 2 - rr.log("classification/line", rr.Scalar(f_of_t)) + rr.log("classification/line", rr.Scalars(f_of_t)) g_of_t = f_of_t + random.uniform(-5.0, 5.0) if g_of_t < f_of_t - 1.5: @@ -112,8 +112,8 @@ def log_classification() -> None: # override instead (see `main()`) rr.log( "classification/samples", - rr.Scalar(g_of_t), - rr.SeriesPoint(color=color, marker_size=marker_size), + rr.Scalars(g_of_t), + rr.SeriesPoints(colors=color, marker_sizes=marker_size), ) @@ -137,17 +137,17 @@ def main() -> None: name="Trig", origin="/trig", overrides={ - "/trig/sin": rr.SeriesLine.from_fields(color=[255, 0, 0], name="sin(0.01t)"), - "/trig/cos": rr.SeriesLine.from_fields(color=[0, 255, 0], name="cos(0.01t)"), + "/trig/sin": rr.SeriesLines.from_fields(colors=[255, 0, 0], names="sin(0.01t)"), + "/trig/cos": rr.SeriesLines.from_fields(colors=[0, 255, 0], names="cos(0.01t)"), }, ), rrb.TimeSeriesView( name="Classification", origin="/classification", overrides={ - "classification/line": rr.SeriesLine.from_fields(color=[255, 255, 0], width=3.0), - # This ensures that the `SeriesPoint` visualizers is used for this entity. - "classification/samples": rrb.VisualizerOverrides("SeriesPoint"), + "classification/line": rr.SeriesLines.from_fields(colors=[255, 255, 0], widths=3.0), + # This ensures that the `SeriesPoints` visualizers is used for this entity. + "classification/samples": rrb.VisualizerOverrides("SeriesPoints"), }, ), ), @@ -155,7 +155,7 @@ def main() -> None: name="Spiral", origin="/spiral", # TODO(#9022): Pluralize series line type. - overrides={"spiral": rr.SeriesLine.from_fields(name=["0.01t cos(0.01t)", "0.01t sin(0.01t)"])}, # type: ignore[arg-type] + overrides={"spiral": rr.SeriesLines.from_fields(names=["0.01t cos(0.01t)", "0.01t sin(0.01t)"])}, # type: ignore[arg-type] ), row_shares=[2, 1], ), diff --git a/examples/python/ros_node/README.md b/examples/python/ros_node/README.md index 4714bbab1ecf..d215d978c9e4 100644 --- a/examples/python/ros_node/README.md +++ b/examples/python/ros_node/README.md @@ -18,7 +18,7 @@ The solution here is mostly a toy example to show how ROS concepts can be mapped ## Used Rerun types -[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole), [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d), [`Boxes3D`](https://www.rerun.io/docs/reference/types/archetypes/boxes3d), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`LineStrips3D`](https://www.rerun.io/docs/reference/types/archetypes/line_strips3d), [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar) +[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole), [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d), [`Boxes3D`](https://www.rerun.io/docs/reference/types/archetypes/boxes3d), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`LineStrips3D`](https://www.rerun.io/docs/reference/types/archetypes/line_strips3d), [`Scalars`](https://www.rerun.io/docs/reference/types/archetypes/scalars?speculative-link) ## Background The [Robot Operating System (ROS)](https://www.ros.org) helps build robot applications through software libraries and tools. diff --git a/examples/python/ros_node/main.py b/examples/python/ros_node/main.py index 882d72574059..c09941f5e9b3 100755 --- a/examples/python/ros_node/main.py +++ b/examples/python/ros_node/main.py @@ -183,8 +183,8 @@ def odom_callback(self, odom: Odometry) -> None: rr.set_time("ros_time", np.datetime64(time.nanoseconds, "ns")) # Capture time-series data for the linear and angular velocities - rr.log("odometry/vel", rr.Scalar(odom.twist.twist.linear.x)) - rr.log("odometry/ang_vel", rr.Scalar(odom.twist.twist.angular.z)) + rr.log("odometry/vel", rr.Scalars(odom.twist.twist.linear.x)) + rr.log("odometry/ang_vel", rr.Scalars(odom.twist.twist.angular.z)) # Update the robot pose itself via TF self.log_tf_as_transform3d("map/robot", time) diff --git a/examples/python/structure_from_motion/README.md b/examples/python/structure_from_motion/README.md index 113b3b657cd0..f05ea32e050f 100644 --- a/examples/python/structure_from_motion/README.md +++ b/examples/python/structure_from_motion/README.md @@ -26,7 +26,7 @@ By using COLMAP in combination with Rerun, a highly-detailed reconstruction of t ## Used Rerun types -[`Points2D`](https://www.rerun.io/docs/reference/types/archetypes/points2d), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d), [`SeriesLine`](https://www.rerun.io/docs/reference/types/archetypes/series_line), [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar), [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole), [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document) +[`Points2D`](https://www.rerun.io/docs/reference/types/archetypes/points2d), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d), [`SeriesLines`](https://www.rerun.io/docs/reference/types/archetypes/series_lines?speculative-link), [`Scalars`](https://www.rerun.io/docs/reference/types/archetypes/scalars?speculative-link), [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole), [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document) ## Logging and visualizing with Rerun @@ -73,11 +73,11 @@ rr.log( ``` ### Reprojection error -For each image a [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar) archetype containing the average reprojection error of the keypoints is logged to the +For each image a [`Scalars`](https://www.rerun.io/docs/reference/types/archetypes/scalars?speculative-link) archetype containing the average reprojection error of the keypoints is logged to the `plot/avg_reproj_err` entity. ```python -rr.log("plot/avg_reproj_err", rr.Scalar(np.mean(point_errors))) +rr.log("plot/avg_reproj_err", rr.Scalars(np.mean(point_errors))) ``` ### 2D points diff --git a/examples/python/structure_from_motion/structure_from_motion/__main__.py b/examples/python/structure_from_motion/structure_from_motion/__main__.py index e01f5cdeafc9..293aca84ac41 100755 --- a/examples/python/structure_from_motion/structure_from_motion/__main__.py +++ b/examples/python/structure_from_motion/structure_from_motion/__main__.py @@ -100,7 +100,7 @@ def read_and_log_sparse_reconstruction(dataset_path: Path, filter_output: bool, rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), static=True) rr.log("/", rr.ViewCoordinates.RIGHT_HAND_Y_DOWN, static=True) - rr.log("plot/avg_reproj_err", rr.SeriesLine(color=[240, 45, 58]), static=True) + rr.log("plot/avg_reproj_err", rr.SeriesLines(colors=[240, 45, 58]), static=True) # Iterate through images (video frames) logging data related to each frame. for image in sorted(images.values(), key=lambda im: im.name): @@ -138,7 +138,7 @@ def read_and_log_sparse_reconstruction(dataset_path: Path, filter_output: bool, point_colors = [point.rgb for point in visible_xyzs] point_errors = [point.error for point in visible_xyzs] - rr.log("plot/avg_reproj_err", rr.Scalar(np.mean(point_errors))) + rr.log("plot/avg_reproj_err", rr.Scalars(np.mean(point_errors))) rr.log("points", rr.Points3D(points, colors=point_colors), rr.AnyValues(error=point_errors)) diff --git a/rerun_cpp/src/rerun/archetypes.hpp b/rerun_cpp/src/rerun/archetypes.hpp index 67999a255cdc..922c394870e5 100644 --- a/rerun_cpp/src/rerun/archetypes.hpp +++ b/rerun_cpp/src/rerun/archetypes.hpp @@ -29,9 +29,12 @@ #include "archetypes/points3d.hpp" #include "archetypes/recording_properties.hpp" #include "archetypes/scalar.hpp" +#include "archetypes/scalars.hpp" #include "archetypes/segmentation_image.hpp" #include "archetypes/series_line.hpp" +#include "archetypes/series_lines.hpp" #include "archetypes/series_point.hpp" +#include "archetypes/series_points.hpp" #include "archetypes/tensor.hpp" #include "archetypes/text_document.hpp" #include "archetypes/text_log.hpp" diff --git a/rerun_cpp/src/rerun/archetypes/.gitattributes b/rerun_cpp/src/rerun/archetypes/.gitattributes index 1c89bc3c16a5..d2f3c92d2bac 100644 --- a/rerun_cpp/src/rerun/archetypes/.gitattributes +++ b/rerun_cpp/src/rerun/archetypes/.gitattributes @@ -55,12 +55,18 @@ recording_properties.cpp linguist-generated=true recording_properties.hpp linguist-generated=true scalar.cpp linguist-generated=true scalar.hpp linguist-generated=true +scalars.cpp linguist-generated=true +scalars.hpp linguist-generated=true segmentation_image.cpp linguist-generated=true segmentation_image.hpp linguist-generated=true series_line.cpp linguist-generated=true series_line.hpp linguist-generated=true +series_lines.cpp linguist-generated=true +series_lines.hpp linguist-generated=true series_point.cpp linguist-generated=true series_point.hpp linguist-generated=true +series_points.cpp linguist-generated=true +series_points.hpp linguist-generated=true tensor.cpp linguist-generated=true tensor.hpp linguist-generated=true text_document.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/archetypes/scalar.cpp b/rerun_cpp/src/rerun/archetypes/scalar.cpp index f0b49becaf0e..4206994d3f72 100644 --- a/rerun_cpp/src/rerun/archetypes/scalar.cpp +++ b/rerun_cpp/src/rerun/archetypes/scalar.cpp @@ -5,6 +5,9 @@ #include "../collection_adapter_builtins.hpp" +RR_PUSH_WARNINGS +RR_DISABLE_DEPRECATION_WARNING + namespace rerun::archetypes { Scalar Scalar::clear_fields() { auto archetype = Scalar(); @@ -55,3 +58,5 @@ namespace rerun { return rerun::take_ownership(std::move(cells)); } } // namespace rerun + +RR_POP_WARNINGS diff --git a/rerun_cpp/src/rerun/archetypes/scalar.hpp b/rerun_cpp/src/rerun/archetypes/scalar.hpp index 72728e3764b2..0aab27a77d9a 100644 --- a/rerun_cpp/src/rerun/archetypes/scalar.hpp +++ b/rerun_cpp/src/rerun/archetypes/scalar.hpp @@ -4,6 +4,7 @@ #pragma once #include "../collection.hpp" +#include "../compiler_utils.hpp" #include "../component_batch.hpp" #include "../component_column.hpp" #include "../components/scalar.hpp" @@ -15,14 +16,17 @@ #include #include +RR_PUSH_WARNINGS +RR_DISABLE_DEPRECATION_WARNING + namespace rerun::archetypes { /// **Archetype**: A double-precision scalar, e.g. for use for time-series plots. /// /// The current timeline value will be used for the time/X-axis, hence scalars - /// cannot be static. + /// should not be static. /// /// When used to produce a plot, this archetype is used to provide the data that - /// is referenced by `archetypes::SeriesLine` or `archetypes::SeriesPoint`. You can do + /// is referenced by `archetypes::SeriesLines` or `archetypes::SeriesPoints`. You can do /// this by logging both archetypes to the same path, or alternatively configuring /// the plot-specific archetypes through the blueprint. /// @@ -42,7 +46,7 @@ namespace rerun::archetypes { /// /// for (int step = 0; step <64; ++step) { /// rec.set_time_sequence("step", step); - /// rec.log("scalars", rerun::Scalar(sin(static_cast(step) / 10.0))); + /// rec.log("scalars", rerun::Scalars(sin(static_cast(step) / 10.0))); /// } /// } /// ``` @@ -73,11 +77,11 @@ namespace rerun::archetypes { /// rec.send_columns( /// "scalars", /// rerun::TimeColumn::from_sequence("step", std::move(times)), - /// rerun::Scalar().with_many_scalar(std::move(scalar_data)).columns() + /// rerun::Scalars(std::move(scalar_data)).columns() /// ); /// } /// ``` - struct Scalar { + struct [[deprecated("Use `Scalars` instead.")]] Scalar { /// The scalar value to log. std::optional scalar; @@ -151,6 +155,8 @@ namespace rerun { /// \private template struct AsComponents; + RR_PUSH_WARNINGS + RR_DISABLE_DEPRECATION_WARNING /// \private template <> @@ -159,3 +165,5 @@ namespace rerun { static Result> as_batches(const archetypes::Scalar& archetype); }; } // namespace rerun + +RR_POP_WARNINGS diff --git a/rerun_cpp/src/rerun/archetypes/scalars.cpp b/rerun_cpp/src/rerun/archetypes/scalars.cpp new file mode 100644 index 000000000000..498f6dbf93a3 --- /dev/null +++ b/rerun_cpp/src/rerun/archetypes/scalars.cpp @@ -0,0 +1,57 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/archetypes/scalars.fbs". + +#include "scalars.hpp" + +#include "../collection_adapter_builtins.hpp" + +namespace rerun::archetypes { + Scalars Scalars::clear_fields() { + auto archetype = Scalars(); + archetype.scalars = + ComponentBatch::empty(Descriptor_scalars).value_or_throw(); + return archetype; + } + + Collection Scalars::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(2); + if (scalars.has_value()) { + columns.push_back(scalars.value().partitioned(lengths_).value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection Scalars::columns() { + if (scalars.has_value()) { + return columns(std::vector(scalars.value().length(), 1)); + } + return Collection(); + } +} // namespace rerun::archetypes + +namespace rerun { + + Result> AsComponents::as_batches( + const archetypes::Scalars& archetype + ) { + using namespace archetypes; + std::vector cells; + cells.reserve(2); + + if (archetype.scalars.has_value()) { + cells.push_back(archetype.scalars.value()); + } + { + auto result = ComponentBatch::from_indicator(); + RR_RETURN_NOT_OK(result.error); + cells.emplace_back(std::move(result.value)); + } + + return rerun::take_ownership(std::move(cells)); + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/archetypes/scalars.hpp b/rerun_cpp/src/rerun/archetypes/scalars.hpp new file mode 100644 index 000000000000..2f985372a38f --- /dev/null +++ b/rerun_cpp/src/rerun/archetypes/scalars.hpp @@ -0,0 +1,153 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/archetypes/scalars.fbs". + +#pragma once + +#include "../collection.hpp" +#include "../component_batch.hpp" +#include "../component_column.hpp" +#include "../components/scalar.hpp" +#include "../indicator_component.hpp" +#include "../result.hpp" + +#include +#include +#include +#include + +namespace rerun::archetypes { + /// **Archetype**: One or more double-precision scalar values, e.g. for use for time-series plots. + /// + /// The current timeline value will be used for the time/X-axis, hence scalars + /// should not be static. + /// Number of scalars per timestamp is expected to be the same over time. + /// + /// When used to produce a plot, this archetype is used to provide the data that + /// is referenced by `archetypes::SeriesLines` or `archetypes::SeriesPoints`. You can do + /// this by logging both archetypes to the same path, or alternatively configuring + /// the plot-specific archetypes through the blueprint. + /// + /// ## Examples + /// + /// ### Update a scalar over time + /// ![image](https://static.rerun.io/transform3d_column_updates/2b7ccfd29349b2b107fcf7eb8a1291a92cf1cafc/full.png) + /// + /// ```cpp + /// #include + /// + /// #include + /// + /// int main() { + /// const auto rec = rerun::RecordingStream("rerun_example_scalar_row_updates"); + /// rec.spawn().exit_on_failure(); + /// + /// for (int step = 0; step <64; ++step) { + /// rec.set_time_sequence("step", step); + /// rec.log("scalars", rerun::Scalars(sin(static_cast(step) / 10.0))); + /// } + /// } + /// ``` + /// + /// ### Update a scalar over time, in a single operation + /// ![image](https://static.rerun.io/transform3d_column_updates/2b7ccfd29349b2b107fcf7eb8a1291a92cf1cafc/full.png) + /// + /// ```cpp + /// #include + /// #include + /// #include + /// + /// #include + /// + /// int main() { + /// const auto rec = rerun::RecordingStream("rerun_example_scalar_column_updates"); + /// rec.spawn().exit_on_failure(); + /// + /// // Native scalars & times. + /// std::vector scalar_data(64); + /// for (size_t i = 0; i <64; ++i) { + /// scalar_data[i] = sin(static_cast(i) / 10.0); + /// } + /// std::vector times(64); + /// std::iota(times.begin(), times.end(), 0); + /// + /// // Serialize to columns and send. + /// rec.send_columns( + /// "scalars", + /// rerun::TimeColumn::from_sequence("step", std::move(times)), + /// rerun::Scalars(std::move(scalar_data)).columns() + /// ); + /// } + /// ``` + struct Scalars { + /// The scalar values to log. + std::optional scalars; + + public: + static constexpr const char IndicatorComponentName[] = "rerun.components.ScalarsIndicator"; + + /// Indicator component, used to identify the archetype when converting to a list of components. + using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.Scalars"; + + /// `ComponentDescriptor` for the `scalars` field. + static constexpr auto Descriptor_scalars = ComponentDescriptor( + ArchetypeName, "scalars", Loggable::Descriptor.component_name + ); + + public: + Scalars() = default; + Scalars(Scalars&& other) = default; + Scalars(const Scalars& other) = default; + Scalars& operator=(const Scalars& other) = default; + Scalars& operator=(Scalars&& other) = default; + + explicit Scalars(Collection _scalars) + : scalars(ComponentBatch::from_loggable(std::move(_scalars), Descriptor_scalars) + .value_or_throw()) {} + + /// Update only some specific fields of a `Scalars`. + static Scalars update_fields() { + return Scalars(); + } + + /// Clear all the fields of a `Scalars`. + static Scalars clear_fields(); + + /// The scalar values to log. + Scalars with_scalars(const Collection& _scalars) && { + scalars = ComponentBatch::from_loggable(_scalars, Descriptor_scalars).value_or_throw(); + return std::move(*this); + } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentBatch::partitioned`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); + }; + +} // namespace rerun::archetypes + +namespace rerun { + /// \private + template + struct AsComponents; + + /// \private + template <> + struct AsComponents { + /// Serialize all set component batches. + static Result> as_batches(const archetypes::Scalars& archetype); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/archetypes/series_line.cpp b/rerun_cpp/src/rerun/archetypes/series_line.cpp index 7007249e6f6b..1dbb68509d68 100644 --- a/rerun_cpp/src/rerun/archetypes/series_line.cpp +++ b/rerun_cpp/src/rerun/archetypes/series_line.cpp @@ -5,6 +5,9 @@ #include "../collection_adapter_builtins.hpp" +RR_PUSH_WARNINGS +RR_DISABLE_DEPRECATION_WARNING + namespace rerun::archetypes { SeriesLine SeriesLine::clear_fields() { auto archetype = SeriesLine(); @@ -102,3 +105,5 @@ namespace rerun { return rerun::take_ownership(std::move(cells)); } } // namespace rerun + +RR_POP_WARNINGS diff --git a/rerun_cpp/src/rerun/archetypes/series_line.hpp b/rerun_cpp/src/rerun/archetypes/series_line.hpp index 458b0b3b8cb2..09532038bc2b 100644 --- a/rerun_cpp/src/rerun/archetypes/series_line.hpp +++ b/rerun_cpp/src/rerun/archetypes/series_line.hpp @@ -4,6 +4,7 @@ #pragma once #include "../collection.hpp" +#include "../compiler_utils.hpp" #include "../component_batch.hpp" #include "../component_column.hpp" #include "../components/aggregation_policy.hpp" @@ -19,12 +20,15 @@ #include #include +RR_PUSH_WARNINGS +RR_DISABLE_DEPRECATION_WARNING + namespace rerun::archetypes { /// **Archetype**: Define the style properties for a line series in a chart. /// /// This archetype only provides styling information and should be logged as static /// when possible. The underlying data needs to be logged to the same entity-path using - /// `archetypes::Scalar`. + /// `archetypes::Scalars`. /// /// ## Example /// @@ -47,23 +51,29 @@ namespace rerun::archetypes { /// // Log two lines series under a shared root so that they show in the same plot by default. /// rec.log_static( /// "trig/sin", - /// rerun::SeriesLine().with_color({255, 0, 0}).with_name("sin(0.01t)").with_width(2) + /// rerun::SeriesLines() + /// .with_colors(rerun::Rgba32{255, 0, 0}) + /// .with_names("sin(0.01t)") + /// .with_widths(2.0f) /// ); /// rec.log_static( /// "trig/cos", - /// rerun::SeriesLine().with_color({0, 255, 0}).with_name("cos(0.01t)").with_width(4) + /// rerun::SeriesLines() + /// .with_colors(rerun::Rgba32{0, 255, 0}) + /// .with_names("cos(0.01t)") + /// .with_widths(4.0f) /// ); /// /// // Log the data on a timeline called "step". /// for (int t = 0; t (TAU * 2.0 * 100.0); ++t) { /// rec.set_time_sequence("step", t); /// - /// rec.log("trig/sin", rerun::Scalar(sin(static_cast(t) / 100.0))); - /// rec.log("trig/cos", rerun::Scalar(cos(static_cast(t) / 100.0))); + /// rec.log("trig/sin", rerun::Scalars(sin(static_cast(t) / 100.0))); + /// rec.log("trig/cos", rerun::Scalars(cos(static_cast(t) / 100.0))); /// } /// } /// ``` - struct SeriesLine { + struct [[deprecated("Use `SeriesLines` instead.")]] SeriesLine { /// Color for the corresponding series. std::optional color; @@ -248,6 +258,8 @@ namespace rerun { /// \private template struct AsComponents; + RR_PUSH_WARNINGS + RR_DISABLE_DEPRECATION_WARNING /// \private template <> @@ -257,3 +269,5 @@ namespace rerun { ); }; } // namespace rerun + +RR_POP_WARNINGS diff --git a/rerun_cpp/src/rerun/archetypes/series_lines.cpp b/rerun_cpp/src/rerun/archetypes/series_lines.cpp new file mode 100644 index 000000000000..3cb84509e632 --- /dev/null +++ b/rerun_cpp/src/rerun/archetypes/series_lines.cpp @@ -0,0 +1,104 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/archetypes/series_lines.fbs". + +#include "series_lines.hpp" + +#include "../collection_adapter_builtins.hpp" + +namespace rerun::archetypes { + SeriesLines SeriesLines::clear_fields() { + auto archetype = SeriesLines(); + archetype.colors = + ComponentBatch::empty(Descriptor_colors).value_or_throw(); + archetype.widths = ComponentBatch::empty(Descriptor_widths) + .value_or_throw(); + archetype.names = + ComponentBatch::empty(Descriptor_names).value_or_throw(); + archetype.visible_series = + ComponentBatch::empty(Descriptor_visible_series) + .value_or_throw(); + archetype.aggregation_policy = ComponentBatch::empty( + Descriptor_aggregation_policy + ) + .value_or_throw(); + return archetype; + } + + Collection SeriesLines::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(6); + if (colors.has_value()) { + columns.push_back(colors.value().partitioned(lengths_).value_or_throw()); + } + if (widths.has_value()) { + columns.push_back(widths.value().partitioned(lengths_).value_or_throw()); + } + if (names.has_value()) { + columns.push_back(names.value().partitioned(lengths_).value_or_throw()); + } + if (visible_series.has_value()) { + columns.push_back(visible_series.value().partitioned(lengths_).value_or_throw()); + } + if (aggregation_policy.has_value()) { + columns.push_back(aggregation_policy.value().partitioned(lengths_).value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection SeriesLines::columns() { + if (colors.has_value()) { + return columns(std::vector(colors.value().length(), 1)); + } + if (widths.has_value()) { + return columns(std::vector(widths.value().length(), 1)); + } + if (names.has_value()) { + return columns(std::vector(names.value().length(), 1)); + } + if (visible_series.has_value()) { + return columns(std::vector(visible_series.value().length(), 1)); + } + if (aggregation_policy.has_value()) { + return columns(std::vector(aggregation_policy.value().length(), 1)); + } + return Collection(); + } +} // namespace rerun::archetypes + +namespace rerun { + + Result> AsComponents::as_batches( + const archetypes::SeriesLines& archetype + ) { + using namespace archetypes; + std::vector cells; + cells.reserve(6); + + if (archetype.colors.has_value()) { + cells.push_back(archetype.colors.value()); + } + if (archetype.widths.has_value()) { + cells.push_back(archetype.widths.value()); + } + if (archetype.names.has_value()) { + cells.push_back(archetype.names.value()); + } + if (archetype.visible_series.has_value()) { + cells.push_back(archetype.visible_series.value()); + } + if (archetype.aggregation_policy.has_value()) { + cells.push_back(archetype.aggregation_policy.value()); + } + { + auto result = ComponentBatch::from_indicator(); + RR_RETURN_NOT_OK(result.error); + cells.emplace_back(std::move(result.value)); + } + + return rerun::take_ownership(std::move(cells)); + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/archetypes/series_lines.hpp b/rerun_cpp/src/rerun/archetypes/series_lines.hpp new file mode 100644 index 000000000000..5b5771442b77 --- /dev/null +++ b/rerun_cpp/src/rerun/archetypes/series_lines.hpp @@ -0,0 +1,271 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/archetypes/series_lines.fbs". + +#pragma once + +#include "../collection.hpp" +#include "../component_batch.hpp" +#include "../component_column.hpp" +#include "../components/aggregation_policy.hpp" +#include "../components/color.hpp" +#include "../components/name.hpp" +#include "../components/series_visible.hpp" +#include "../components/stroke_width.hpp" +#include "../indicator_component.hpp" +#include "../result.hpp" + +#include +#include +#include +#include + +namespace rerun::archetypes { + /// **Archetype**: Define the style properties for one or more line series in a chart. + /// + /// This archetype only provides styling information. + /// Changes over time are supported for most but not all its fields (see respective fields for details), + /// it's generally recommended to log this type as static. + /// + /// The underlying data needs to be logged to the same entity-path using `archetypes::Scalars`. + /// Dimensionality of the scalar arrays logged at each time point is assumed to be the same over time. + /// + /// ## Example + /// + /// ### Line series + /// ![image](https://static.rerun.io/series_line_style/d2616d98b1e46bdb85849b8669154fdf058e3453/full.png) + /// + /// ```cpp + /// #include + /// + /// #include + /// + /// constexpr float TAU = 6.28318530717958647692528676655900577f; + /// + /// int main() { + /// const auto rec = rerun::RecordingStream("rerun_example_series_line_style"); + /// rec.spawn().exit_on_failure(); + /// + /// // Set up plot styling: + /// // They are logged static as they don't change over time and apply to all timelines. + /// // Log two lines series under a shared root so that they show in the same plot by default. + /// rec.log_static( + /// "trig/sin", + /// rerun::SeriesLines() + /// .with_colors(rerun::Rgba32{255, 0, 0}) + /// .with_names("sin(0.01t)") + /// .with_widths(2.0f) + /// ); + /// rec.log_static( + /// "trig/cos", + /// rerun::SeriesLines() + /// .with_colors(rerun::Rgba32{0, 255, 0}) + /// .with_names("cos(0.01t)") + /// .with_widths(4.0f) + /// ); + /// + /// // Log the data on a timeline called "step". + /// for (int t = 0; t (TAU * 2.0 * 100.0); ++t) { + /// rec.set_time_sequence("step", t); + /// + /// rec.log("trig/sin", rerun::Scalars(sin(static_cast(t) / 100.0))); + /// rec.log("trig/cos", rerun::Scalars(cos(static_cast(t) / 100.0))); + /// } + /// } + /// ``` + struct SeriesLines { + /// Color for the corresponding series. + /// + /// May change over time, but can cause discontinuities in the line. + std::optional colors; + + /// Stroke width for the corresponding series. + /// + /// May change over time, but can cause discontinuities in the line. + std::optional widths; + + /// Display name of the series. + /// + /// Used in the legend. Expected to be unchanging over time. + std::optional names; + + /// Which lines are visible. + /// + /// If not set, all line series on this entity are visible. + /// Unlike with the regular visibility property of the entire entity, any series that is hidden + /// via this property will still be visible in the legend. + /// + /// May change over time, but can cause discontinuities in the line. + std::optional visible_series; + + /// Configures the zoom-dependent scalar aggregation. + /// + /// This is done only if steps on the X axis go below a single pixel, + /// i.e. a single pixel covers more than one tick worth of data. It can greatly improve performance + /// (and readability) in such situations as it prevents overdraw. + /// + /// Expected to be unchanging over time. + std::optional aggregation_policy; + + public: + static constexpr const char IndicatorComponentName[] = + "rerun.components.SeriesLinesIndicator"; + + /// Indicator component, used to identify the archetype when converting to a list of components. + using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.SeriesLines"; + + /// `ComponentDescriptor` for the `colors` field. + static constexpr auto Descriptor_colors = ComponentDescriptor( + ArchetypeName, "colors", Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `widths` field. + static constexpr auto Descriptor_widths = ComponentDescriptor( + ArchetypeName, "widths", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `names` field. + static constexpr auto Descriptor_names = ComponentDescriptor( + ArchetypeName, "names", Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `visible_series` field. + static constexpr auto Descriptor_visible_series = ComponentDescriptor( + ArchetypeName, "visible_series", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `aggregation_policy` field. + static constexpr auto Descriptor_aggregation_policy = ComponentDescriptor( + ArchetypeName, "aggregation_policy", + Loggable::Descriptor.component_name + ); + + public: // START of extensions from series_lines_ext.cpp: + // Overload needed to avoid confusion with passing single strings. + /// Display name of the series. + /// + /// Used in the legend. Expected to be unchanging over time. + SeriesLines with_names(const char* _name) && { + names = ComponentBatch::from_loggable(rerun::components::Name(_name), Descriptor_names) + .value_or_throw(); + return std::move(*this); + } + + // END of extensions from series_lines_ext.cpp, start of generated code: + + public: + SeriesLines() = default; + SeriesLines(SeriesLines&& other) = default; + SeriesLines(const SeriesLines& other) = default; + SeriesLines& operator=(const SeriesLines& other) = default; + SeriesLines& operator=(SeriesLines&& other) = default; + + /// Update only some specific fields of a `SeriesLines`. + static SeriesLines update_fields() { + return SeriesLines(); + } + + /// Clear all the fields of a `SeriesLines`. + static SeriesLines clear_fields(); + + /// Color for the corresponding series. + /// + /// May change over time, but can cause discontinuities in the line. + SeriesLines with_colors(const Collection& _colors) && { + colors = ComponentBatch::from_loggable(_colors, Descriptor_colors).value_or_throw(); + return std::move(*this); + } + + /// Stroke width for the corresponding series. + /// + /// May change over time, but can cause discontinuities in the line. + SeriesLines with_widths(const Collection& _widths) && { + widths = ComponentBatch::from_loggable(_widths, Descriptor_widths).value_or_throw(); + return std::move(*this); + } + + /// Display name of the series. + /// + /// Used in the legend. Expected to be unchanging over time. + SeriesLines with_names(const Collection& _names) && { + names = ComponentBatch::from_loggable(_names, Descriptor_names).value_or_throw(); + return std::move(*this); + } + + /// Which lines are visible. + /// + /// If not set, all line series on this entity are visible. + /// Unlike with the regular visibility property of the entire entity, any series that is hidden + /// via this property will still be visible in the legend. + /// + /// May change over time, but can cause discontinuities in the line. + SeriesLines with_visible_series( + const Collection& _visible_series + ) && { + visible_series = + ComponentBatch::from_loggable(_visible_series, Descriptor_visible_series) + .value_or_throw(); + return std::move(*this); + } + + /// Configures the zoom-dependent scalar aggregation. + /// + /// This is done only if steps on the X axis go below a single pixel, + /// i.e. a single pixel covers more than one tick worth of data. It can greatly improve performance + /// (and readability) in such situations as it prevents overdraw. + /// + /// Expected to be unchanging over time. + SeriesLines with_aggregation_policy( + const rerun::components::AggregationPolicy& _aggregation_policy + ) && { + aggregation_policy = + ComponentBatch::from_loggable(_aggregation_policy, Descriptor_aggregation_policy) + .value_or_throw(); + return std::move(*this); + } + + /// This method makes it possible to pack multiple `aggregation_policy` in a single component batch. + /// + /// This only makes sense when used in conjunction with `columns`. `with_aggregation_policy` should + /// be used when logging a single row's worth of data. + SeriesLines with_many_aggregation_policy( + const Collection& _aggregation_policy + ) && { + aggregation_policy = + ComponentBatch::from_loggable(_aggregation_policy, Descriptor_aggregation_policy) + .value_or_throw(); + return std::move(*this); + } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentBatch::partitioned`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); + }; + +} // namespace rerun::archetypes + +namespace rerun { + /// \private + template + struct AsComponents; + + /// \private + template <> + struct AsComponents { + /// Serialize all set component batches. + static Result> as_batches( + const archetypes::SeriesLines& archetype + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/archetypes/series_lines_ext.cpp b/rerun_cpp/src/rerun/archetypes/series_lines_ext.cpp new file mode 100644 index 000000000000..9407ddadff63 --- /dev/null +++ b/rerun_cpp/src/rerun/archetypes/series_lines_ext.cpp @@ -0,0 +1,21 @@ +#if 0 + +#include "series_lines.hpp" + +namespace rerun::archetypes { + // + + // Overload needed to avoid confusion with passing single strings. + /// Display name of the series. + /// + /// Used in the legend. Expected to be unchanging over time. + SeriesLines with_names(const char* _name) && { + names = ComponentBatch::from_loggable(rerun::components::Name(_name), Descriptor_names).value_or_throw(); + return std::move(*this); + } + + // + +} // namespace rerun::archetypes + +#endif diff --git a/rerun_cpp/src/rerun/archetypes/series_point.cpp b/rerun_cpp/src/rerun/archetypes/series_point.cpp index 843be47fde39..cc0f2584bc70 100644 --- a/rerun_cpp/src/rerun/archetypes/series_point.cpp +++ b/rerun_cpp/src/rerun/archetypes/series_point.cpp @@ -5,6 +5,9 @@ #include "../collection_adapter_builtins.hpp" +RR_PUSH_WARNINGS +RR_DISABLE_DEPRECATION_WARNING + namespace rerun::archetypes { SeriesPoint SeriesPoint::clear_fields() { auto archetype = SeriesPoint(); @@ -101,3 +104,5 @@ namespace rerun { return rerun::take_ownership(std::move(cells)); } } // namespace rerun + +RR_POP_WARNINGS diff --git a/rerun_cpp/src/rerun/archetypes/series_point.hpp b/rerun_cpp/src/rerun/archetypes/series_point.hpp index 3da3cb2db92d..109958d36aab 100644 --- a/rerun_cpp/src/rerun/archetypes/series_point.hpp +++ b/rerun_cpp/src/rerun/archetypes/series_point.hpp @@ -4,6 +4,7 @@ #pragma once #include "../collection.hpp" +#include "../compiler_utils.hpp" #include "../component_batch.hpp" #include "../component_column.hpp" #include "../components/color.hpp" @@ -19,12 +20,15 @@ #include #include +RR_PUSH_WARNINGS +RR_DISABLE_DEPRECATION_WARNING + namespace rerun::archetypes { /// **Archetype**: Define the style properties for a point series in a chart. /// /// This archetype only provides styling information and should be logged as static /// when possible. The underlying data needs to be logged to the same entity-path using - /// `archetypes::Scalar`. + /// `archetypes::Scalars`. /// /// ## Example /// @@ -47,31 +51,31 @@ namespace rerun::archetypes { /// // Log two point series under a shared root so that they show in the same plot by default. /// rec.log_static( /// "trig/sin", - /// rerun::SeriesPoint() - /// .with_color({255, 0, 0}) - /// .with_name("sin(0.01t)") - /// .with_marker(rerun::components::MarkerShape::Circle) - /// .with_marker_size(4) + /// rerun::SeriesPoints() + /// .with_colors(rerun::Rgba32{255, 0, 0}) + /// .with_names("sin(0.01t)") + /// .with_markers(rerun::components::MarkerShape::Circle) + /// .with_marker_sizes(4.0f) /// ); /// rec.log_static( /// "trig/cos", - /// rerun::SeriesPoint() - /// .with_color({0, 255, 0}) - /// .with_name("cos(0.01t)") - /// .with_marker(rerun::components::MarkerShape::Cross) - /// .with_marker_size(2) + /// rerun::SeriesPoints() + /// .with_colors(rerun::Rgba32{0, 255, 0}) + /// .with_names("cos(0.01t)") + /// .with_markers(rerun::components::MarkerShape::Cross) + /// .with_marker_sizes(2.0f) /// ); /// /// // Log the data on a timeline called "step". /// for (int t = 0; t (TAU * 2.0 * 10.0); ++t) { /// rec.set_time_sequence("step", t); /// - /// rec.log("trig/sin", rerun::Scalar(sin(static_cast(t) / 10.0))); - /// rec.log("trig/cos", rerun::Scalar(cos(static_cast(t) / 10.0))); + /// rec.log("trig/sin", rerun::Scalars(sin(static_cast(t) / 10.0))); + /// rec.log("trig/cos", rerun::Scalars(cos(static_cast(t) / 10.0))); /// } /// } /// ``` - struct SeriesPoint { + struct [[deprecated("Use `SeriesPoints` instead.")]] SeriesPoint { /// Color for the corresponding series. std::optional color; @@ -244,6 +248,8 @@ namespace rerun { /// \private template struct AsComponents; + RR_PUSH_WARNINGS + RR_DISABLE_DEPRECATION_WARNING /// \private template <> @@ -254,3 +260,5 @@ namespace rerun { ); }; } // namespace rerun + +RR_POP_WARNINGS diff --git a/rerun_cpp/src/rerun/archetypes/series_points.cpp b/rerun_cpp/src/rerun/archetypes/series_points.cpp new file mode 100644 index 000000000000..a10b148e49cf --- /dev/null +++ b/rerun_cpp/src/rerun/archetypes/series_points.cpp @@ -0,0 +1,104 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/archetypes/series_points.fbs". + +#include "series_points.hpp" + +#include "../collection_adapter_builtins.hpp" + +namespace rerun::archetypes { + SeriesPoints SeriesPoints::clear_fields() { + auto archetype = SeriesPoints(); + archetype.colors = + ComponentBatch::empty(Descriptor_colors).value_or_throw(); + archetype.markers = + ComponentBatch::empty(Descriptor_markers) + .value_or_throw(); + archetype.names = + ComponentBatch::empty(Descriptor_names).value_or_throw(); + archetype.visible_series = + ComponentBatch::empty(Descriptor_visible_series) + .value_or_throw(); + archetype.marker_sizes = + ComponentBatch::empty(Descriptor_marker_sizes) + .value_or_throw(); + return archetype; + } + + Collection SeriesPoints::columns(const Collection& lengths_) { + std::vector columns; + columns.reserve(6); + if (colors.has_value()) { + columns.push_back(colors.value().partitioned(lengths_).value_or_throw()); + } + if (markers.has_value()) { + columns.push_back(markers.value().partitioned(lengths_).value_or_throw()); + } + if (names.has_value()) { + columns.push_back(names.value().partitioned(lengths_).value_or_throw()); + } + if (visible_series.has_value()) { + columns.push_back(visible_series.value().partitioned(lengths_).value_or_throw()); + } + if (marker_sizes.has_value()) { + columns.push_back(marker_sizes.value().partitioned(lengths_).value_or_throw()); + } + columns.push_back( + ComponentColumn::from_indicators(static_cast(lengths_.size())) + .value_or_throw() + ); + return columns; + } + + Collection SeriesPoints::columns() { + if (colors.has_value()) { + return columns(std::vector(colors.value().length(), 1)); + } + if (markers.has_value()) { + return columns(std::vector(markers.value().length(), 1)); + } + if (names.has_value()) { + return columns(std::vector(names.value().length(), 1)); + } + if (visible_series.has_value()) { + return columns(std::vector(visible_series.value().length(), 1)); + } + if (marker_sizes.has_value()) { + return columns(std::vector(marker_sizes.value().length(), 1)); + } + return Collection(); + } +} // namespace rerun::archetypes + +namespace rerun { + + Result> AsComponents::as_batches( + const archetypes::SeriesPoints& archetype + ) { + using namespace archetypes; + std::vector cells; + cells.reserve(6); + + if (archetype.colors.has_value()) { + cells.push_back(archetype.colors.value()); + } + if (archetype.markers.has_value()) { + cells.push_back(archetype.markers.value()); + } + if (archetype.names.has_value()) { + cells.push_back(archetype.names.value()); + } + if (archetype.visible_series.has_value()) { + cells.push_back(archetype.visible_series.value()); + } + if (archetype.marker_sizes.has_value()) { + cells.push_back(archetype.marker_sizes.value()); + } + { + auto result = ComponentBatch::from_indicator(); + RR_RETURN_NOT_OK(result.error); + cells.emplace_back(std::move(result.value)); + } + + return rerun::take_ownership(std::move(cells)); + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/archetypes/series_points.hpp b/rerun_cpp/src/rerun/archetypes/series_points.hpp new file mode 100644 index 000000000000..f561fa5cc817 --- /dev/null +++ b/rerun_cpp/src/rerun/archetypes/series_points.hpp @@ -0,0 +1,251 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/archetypes/series_points.fbs". + +#pragma once + +#include "../collection.hpp" +#include "../component_batch.hpp" +#include "../component_column.hpp" +#include "../components/color.hpp" +#include "../components/marker_shape.hpp" +#include "../components/marker_size.hpp" +#include "../components/name.hpp" +#include "../components/series_visible.hpp" +#include "../indicator_component.hpp" +#include "../result.hpp" + +#include +#include +#include +#include + +namespace rerun::archetypes { + /// **Archetype**: Define the style properties for one or more point series (scatter plot) in a chart. + /// + /// This archetype only provides styling information. + /// Changes over time are supported for most but not all its fields (see respective fields for details), + /// it's generally recommended to log this type as static. + /// + /// The underlying data needs to be logged to the same entity-path using `archetypes::Scalars`. + /// Dimensionality of the scalar arrays logged at each time point is assumed to be the same over time. + /// + /// ## Example + /// + /// ### Point series + /// ![image](https://static.rerun.io/series_point_style/82207a705da6c086b28ce161db1db9e8b12258b7/full.png) + /// + /// ```cpp + /// #include + /// + /// #include + /// + /// constexpr float TAU = 6.28318530717958647692528676655900577f; + /// + /// int main() { + /// const auto rec = rerun::RecordingStream("rerun_example_series_point_style"); + /// rec.spawn().exit_on_failure(); + /// + /// // Set up plot styling: + /// // They are logged static as they don't change over time and apply to all timelines. + /// // Log two point series under a shared root so that they show in the same plot by default. + /// rec.log_static( + /// "trig/sin", + /// rerun::SeriesPoints() + /// .with_colors(rerun::Rgba32{255, 0, 0}) + /// .with_names("sin(0.01t)") + /// .with_markers(rerun::components::MarkerShape::Circle) + /// .with_marker_sizes(4.0f) + /// ); + /// rec.log_static( + /// "trig/cos", + /// rerun::SeriesPoints() + /// .with_colors(rerun::Rgba32{0, 255, 0}) + /// .with_names("cos(0.01t)") + /// .with_markers(rerun::components::MarkerShape::Cross) + /// .with_marker_sizes(2.0f) + /// ); + /// + /// // Log the data on a timeline called "step". + /// for (int t = 0; t (TAU * 2.0 * 10.0); ++t) { + /// rec.set_time_sequence("step", t); + /// + /// rec.log("trig/sin", rerun::Scalars(sin(static_cast(t) / 10.0))); + /// rec.log("trig/cos", rerun::Scalars(cos(static_cast(t) / 10.0))); + /// } + /// } + /// ``` + struct SeriesPoints { + /// Color for the corresponding series. + /// + /// May change over time, but can cause discontinuities in the line. + std::optional colors; + + /// What shape to use to represent the point + /// + /// May change over time. + std::optional markers; + + /// Display name of the series. + /// + /// Used in the legend. Expected to be unchanging over time. + std::optional names; + + /// Which lines are visible. + /// + /// If not set, all line series on this entity are visible. + /// Unlike with the regular visibility property of the entire entity, any series that is hidden + /// via this property will still be visible in the legend. + /// + /// May change over time. + std::optional visible_series; + + /// Sizes of the markers. + /// + /// May change over time. + std::optional marker_sizes; + + public: + static constexpr const char IndicatorComponentName[] = + "rerun.components.SeriesPointsIndicator"; + + /// Indicator component, used to identify the archetype when converting to a list of components. + using IndicatorComponent = rerun::components::IndicatorComponent; + /// The name of the archetype as used in `ComponentDescriptor`s. + static constexpr const char ArchetypeName[] = "rerun.archetypes.SeriesPoints"; + + /// `ComponentDescriptor` for the `colors` field. + static constexpr auto Descriptor_colors = ComponentDescriptor( + ArchetypeName, "colors", Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `markers` field. + static constexpr auto Descriptor_markers = ComponentDescriptor( + ArchetypeName, "markers", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `names` field. + static constexpr auto Descriptor_names = ComponentDescriptor( + ArchetypeName, "names", Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `visible_series` field. + static constexpr auto Descriptor_visible_series = ComponentDescriptor( + ArchetypeName, "visible_series", + Loggable::Descriptor.component_name + ); + /// `ComponentDescriptor` for the `marker_sizes` field. + static constexpr auto Descriptor_marker_sizes = ComponentDescriptor( + ArchetypeName, "marker_sizes", + Loggable::Descriptor.component_name + ); + + public: // START of extensions from series_points_ext.cpp: + // Overload needed to avoid confusion with passing single strings. + /// Display name of the series. + /// + /// Used in the legend. Expected to be unchanging over time. + SeriesPoints with_names(const char* _name) && { + names = ComponentBatch::from_loggable(rerun::components::Name(_name), Descriptor_names) + .value_or_throw(); + return std::move(*this); + } + + // END of extensions from series_points_ext.cpp, start of generated code: + + public: + SeriesPoints() = default; + SeriesPoints(SeriesPoints&& other) = default; + SeriesPoints(const SeriesPoints& other) = default; + SeriesPoints& operator=(const SeriesPoints& other) = default; + SeriesPoints& operator=(SeriesPoints&& other) = default; + + /// Update only some specific fields of a `SeriesPoints`. + static SeriesPoints update_fields() { + return SeriesPoints(); + } + + /// Clear all the fields of a `SeriesPoints`. + static SeriesPoints clear_fields(); + + /// Color for the corresponding series. + /// + /// May change over time, but can cause discontinuities in the line. + SeriesPoints with_colors(const Collection& _colors) && { + colors = ComponentBatch::from_loggable(_colors, Descriptor_colors).value_or_throw(); + return std::move(*this); + } + + /// What shape to use to represent the point + /// + /// May change over time. + SeriesPoints with_markers(const Collection& _markers) && { + markers = ComponentBatch::from_loggable(_markers, Descriptor_markers).value_or_throw(); + return std::move(*this); + } + + /// Display name of the series. + /// + /// Used in the legend. Expected to be unchanging over time. + SeriesPoints with_names(const Collection& _names) && { + names = ComponentBatch::from_loggable(_names, Descriptor_names).value_or_throw(); + return std::move(*this); + } + + /// Which lines are visible. + /// + /// If not set, all line series on this entity are visible. + /// Unlike with the regular visibility property of the entire entity, any series that is hidden + /// via this property will still be visible in the legend. + /// + /// May change over time. + SeriesPoints with_visible_series( + const Collection& _visible_series + ) && { + visible_series = + ComponentBatch::from_loggable(_visible_series, Descriptor_visible_series) + .value_or_throw(); + return std::move(*this); + } + + /// Sizes of the markers. + /// + /// May change over time. + SeriesPoints with_marker_sizes( + const Collection& _marker_sizes + ) && { + marker_sizes = ComponentBatch::from_loggable(_marker_sizes, Descriptor_marker_sizes) + .value_or_throw(); + return std::move(*this); + } + + /// Partitions the component data into multiple sub-batches. + /// + /// Specifically, this transforms the existing `ComponentBatch` data into `ComponentColumn`s + /// instead, via `ComponentBatch::partitioned`. + /// + /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun. + /// + /// The specified `lengths` must sum to the total length of the component batch. + Collection columns(const Collection& lengths_); + + /// Partitions the component data into unit-length sub-batches. + /// + /// This is semantically similar to calling `columns` with `std::vector(n, 1)`, + /// where `n` is automatically guessed. + Collection columns(); + }; + +} // namespace rerun::archetypes + +namespace rerun { + /// \private + template + struct AsComponents; + + /// \private + template <> + struct AsComponents { + /// Serialize all set component batches. + static Result> as_batches( + const archetypes::SeriesPoints& archetype + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/archetypes/series_points_ext.cpp b/rerun_cpp/src/rerun/archetypes/series_points_ext.cpp new file mode 100644 index 000000000000..062996f5211b --- /dev/null +++ b/rerun_cpp/src/rerun/archetypes/series_points_ext.cpp @@ -0,0 +1,21 @@ +#if 0 + +#include "series_points.hpp" + +namespace rerun::archetypes { + // + + // Overload needed to avoid confusion with passing single strings. + /// Display name of the series. + /// + /// Used in the legend. Expected to be unchanging over time. + SeriesPoints with_names(const char* _name) && { + names = ComponentBatch::from_loggable(rerun::components::Name(_name), Descriptor_names).value_or_throw(); + return std::move(*this); + } + + // + +} // namespace rerun::archetypes + +#endif diff --git a/rerun_py/docs/gen_common_index.py b/rerun_py/docs/gen_common_index.py index 4bab77a5e47f..c2febbc5a181 100755 --- a/rerun_py/docs/gen_common_index.py +++ b/rerun_py/docs/gen_common_index.py @@ -194,9 +194,9 @@ class Section: title="Plotting", class_list=[ "archetypes.BarChart", - "archetypes.Scalar", - "archetypes.SeriesLine", - "archetypes.SeriesPoint", + "archetypes.Scalars", + "archetypes.SeriesLines", + "archetypes.SeriesPoints", ], gen_page=False, ), @@ -257,6 +257,15 @@ class Section: ], gen_page=False, ), + Section( + title="Deprecated", + class_list=[ + "archetypes.Scalar", + "archetypes.SeriesLine", + "archetypes.SeriesPoint", + ], + gen_page=False, + ), ################################################################################ # Other referenced things Section( diff --git a/rerun_py/rerun_sdk/rerun/__init__.py b/rerun_py/rerun_sdk/rerun/__init__.py index aa59d898b74e..cda326164cb6 100644 --- a/rerun_py/rerun_sdk/rerun/__init__.py +++ b/rerun_py/rerun_sdk/rerun/__init__.py @@ -95,9 +95,12 @@ Points2D as Points2D, Points3D as Points3D, Scalar as Scalar, + Scalars as Scalars, SegmentationImage as SegmentationImage, SeriesLine as SeriesLine, + SeriesLines as SeriesLines, SeriesPoint as SeriesPoint, + SeriesPoints as SeriesPoints, Tensor as Tensor, TextDocument as TextDocument, TextLog as TextLog, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/.gitattributes b/rerun_py/rerun_sdk/rerun/archetypes/.gitattributes index 80cccae2949c..39048b01f356 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/archetypes/.gitattributes @@ -29,9 +29,12 @@ points2d.py linguist-generated=true points3d.py linguist-generated=true recording_properties.py linguist-generated=true scalar.py linguist-generated=true +scalars.py linguist-generated=true segmentation_image.py linguist-generated=true series_line.py linguist-generated=true +series_lines.py linguist-generated=true series_point.py linguist-generated=true +series_points.py linguist-generated=true tensor.py linguist-generated=true text_document.py linguist-generated=true text_log.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/archetypes/__init__.py b/rerun_py/rerun_sdk/rerun/archetypes/__init__.py index ad112cb8783d..5c839a78a18d 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/__init__.py @@ -29,9 +29,12 @@ from .points3d import Points3D from .recording_properties import RecordingProperties from .scalar import Scalar +from .scalars import Scalars from .segmentation_image import SegmentationImage from .series_line import SeriesLine +from .series_lines import SeriesLines from .series_point import SeriesPoint +from .series_points import SeriesPoints from .tensor import Tensor from .text_document import TextDocument from .text_log import TextLog @@ -67,9 +70,12 @@ "Points3D", "RecordingProperties", "Scalar", + "Scalars", "SegmentationImage", "SeriesLine", + "SeriesLines", "SeriesPoint", + "SeriesPoints", "Tensor", "TextDocument", "TextLog", diff --git a/rerun_py/rerun_sdk/rerun/archetypes/scalar.py b/rerun_py/rerun_sdk/rerun/archetypes/scalar.py index 2c3ecdd2e890..9a4054b0bd4d 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/scalar.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/scalar.py @@ -10,6 +10,7 @@ import numpy as np import pyarrow as pa from attrs import define, field +from typing_extensions import deprecated # type: ignore[misc, unused-ignore] from .. import components, datatypes from .._baseclasses import ( @@ -21,16 +22,17 @@ __all__ = ["Scalar"] +@deprecated("""Use `Scalars` instead.""") @define(str=False, repr=False, init=False) class Scalar(Archetype): """ **Archetype**: A double-precision scalar, e.g. for use for time-series plots. The current timeline value will be used for the time/X-axis, hence scalars - cannot be static. + should not be static. When used to produce a plot, this archetype is used to provide the data that - is referenced by [`archetypes.SeriesLine`][rerun.archetypes.SeriesLine] or [`archetypes.SeriesPoint`][rerun.archetypes.SeriesPoint]. You can do + is referenced by [`archetypes.SeriesLines`][rerun.archetypes.SeriesLines] or [`archetypes.SeriesPoints`][rerun.archetypes.SeriesPoints]. You can do this by logging both archetypes to the same path, or alternatively configuring the plot-specific archetypes through the blueprint. @@ -48,7 +50,7 @@ class Scalar(Archetype): for step in range(64): rr.set_time("step", sequence=step) - rr.log("scalars", rr.Scalar(math.sin(step / 10.0))) + rr.log("scalars", rr.Scalars(math.sin(step / 10.0))) ```
@@ -75,7 +77,7 @@ class Scalar(Archetype): rr.send_columns( "scalars", indexes=[rr.TimeColumn("step", sequence=times)], - columns=rr.Scalar.columns(scalar=scalars), + columns=rr.Scalars.columns(scalars=scalars), ) ```
@@ -114,6 +116,7 @@ def __attrs_clear__(self) -> None: ) @classmethod + @deprecated("""Use `Scalars` instead.""") def _clear(cls) -> Scalar: """Produce an empty Scalar, bypassing `__init__`.""" inst = cls.__new__(cls) @@ -121,6 +124,7 @@ def _clear(cls) -> Scalar: return inst @classmethod + @deprecated("""Use `Scalars` instead.""") def from_fields( cls, *, @@ -160,6 +164,7 @@ def cleared(cls) -> Scalar: return cls.from_fields(clear_unset=True) @classmethod + @deprecated("""Use `Scalars` instead.""") def columns( cls, *, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/scalars.py b/rerun_py/rerun_sdk/rerun/archetypes/scalars.py new file mode 100644 index 000000000000..27c3db8e4294 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/archetypes/scalars.py @@ -0,0 +1,234 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/archetypes/scalars.fbs". + +# You can extend this class by creating a "ScalarsExt" class in "scalars_ext.py". + +from __future__ import annotations + +from typing import Any + +import numpy as np +import pyarrow as pa +from attrs import define, field + +from .. import components, datatypes +from .._baseclasses import ( + Archetype, + ComponentColumnList, +) +from ..error_utils import catch_and_log_exceptions + +__all__ = ["Scalars"] + + +@define(str=False, repr=False, init=False) +class Scalars(Archetype): + """ + **Archetype**: One or more double-precision scalar values, e.g. for use for time-series plots. + + The current timeline value will be used for the time/X-axis, hence scalars + should not be static. + Number of scalars per timestamp is expected to be the same over time. + + When used to produce a plot, this archetype is used to provide the data that + is referenced by [`archetypes.SeriesLines`][rerun.archetypes.SeriesLines] or [`archetypes.SeriesPoints`][rerun.archetypes.SeriesPoints]. You can do + this by logging both archetypes to the same path, or alternatively configuring + the plot-specific archetypes through the blueprint. + + Examples + -------- + ### Update a scalar over time: + ```python + from __future__ import annotations + + import math + + import rerun as rr + + rr.init("rerun_example_scalar_row_updates", spawn=True) + + for step in range(64): + rr.set_time("step", sequence=step) + rr.log("scalars", rr.Scalars(math.sin(step / 10.0))) + ``` +
+ + + + + + + +
+ + ### Update a scalar over time, in a single operation: + ```python + from __future__ import annotations + + import numpy as np + import rerun as rr + + rr.init("rerun_example_scalar_column_updates", spawn=True) + + times = np.arange(0, 64) + scalars = np.sin(times / 10.0) + + rr.send_columns( + "scalars", + indexes=[rr.TimeColumn("step", sequence=times)], + columns=rr.Scalars.columns(scalars=scalars), + ) + ``` +
+ + + + + + + +
+ + """ + + def __init__(self: Any, scalars: datatypes.Float64ArrayLike) -> None: + """ + Create a new instance of the Scalars archetype. + + Parameters + ---------- + scalars: + The scalar values to log. + + """ + + # You can define your own __init__ function as a member of ScalarsExt in scalars_ext.py + with catch_and_log_exceptions(context=self.__class__.__name__): + self.__attrs_init__(scalars=scalars) + return + self.__attrs_clear__() + + def __attrs_clear__(self) -> None: + """Convenience method for calling `__attrs_init__` with all `None`s.""" + self.__attrs_init__( + scalars=None, + ) + + @classmethod + def _clear(cls) -> Scalars: + """Produce an empty Scalars, bypassing `__init__`.""" + inst = cls.__new__(cls) + inst.__attrs_clear__() + return inst + + @classmethod + def from_fields( + cls, + *, + clear_unset: bool = False, + scalars: datatypes.Float64ArrayLike | None = None, + ) -> Scalars: + """ + Update only some specific fields of a `Scalars`. + + Parameters + ---------- + clear_unset: + If true, all unspecified fields will be explicitly cleared. + scalars: + The scalar values to log. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "scalars": scalars, + } + + if clear_unset: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def cleared(cls) -> Scalars: + """Clear all the fields of a `Scalars`.""" + return cls.from_fields(clear_unset=True) + + @classmethod + def columns( + cls, + *, + scalars: datatypes.Float64ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + scalars: + The scalar values to log. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + scalars=scalars, + ) + + batches = inst.as_component_batches(include_indicators=False) + if len(batches) == 0: + return ComponentColumnList([]) + + kwargs = {"scalars": scalars} + columns = [] + + for batch in batches: + arrow_array = batch.as_arrow_array() + + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): + param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] + shape = np.shape(param) # type: ignore[arg-type] + + if pa.types.is_fixed_size_list(arrow_array.type) and len(shape) <= 2: + # If shape length is 2 or less, we have `num_rows` single element batches (each element is a fixed sized list). + # `shape[1]` should be the length of the fixed sized list. + # (This should have been already validated by conversion to the arrow_array) + batch_length = 1 + else: + batch_length = shape[1] if len(shape) > 1 else 1 # type: ignore[redundant-expr,misc] + + num_rows = shape[0] if len(shape) >= 1 else 1 # type: ignore[redundant-expr,misc] + sizes = batch_length * np.ones(num_rows) + else: + # For non-primitive types, default to partitioning each element separately. + sizes = np.ones(len(arrow_array)) + + columns.append(batch.partition(sizes)) + + indicator_column = cls.indicator().partition(np.zeros(len(sizes))) + return ComponentColumnList([indicator_column] + columns) + + scalars: components.ScalarBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.ScalarBatch._converter, # type: ignore[misc] + ) + # The scalar values to log. + # + # (Docstring intentionally commented out to hide this field from the docs) + + __str__ = Archetype.__str__ + __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/series_line.py b/rerun_py/rerun_sdk/rerun/archetypes/series_line.py index 803e6f84f726..99b22a9307c2 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/series_line.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/series_line.py @@ -10,6 +10,7 @@ import numpy as np import pyarrow as pa from attrs import define, field +from typing_extensions import deprecated # type: ignore[misc, unused-ignore] from .. import components, datatypes from .._baseclasses import ( @@ -21,6 +22,7 @@ __all__ = ["SeriesLine"] +@deprecated("""Use `SeriesLines` instead.""") @define(str=False, repr=False, init=False) class SeriesLine(Archetype): """ @@ -28,7 +30,7 @@ class SeriesLine(Archetype): This archetype only provides styling information and should be logged as static when possible. The underlying data needs to be logged to the same entity-path using - [`archetypes.Scalar`][rerun.archetypes.Scalar]. + [`archetypes.Scalars`][rerun.archetypes.Scalars]. Example ------- @@ -43,15 +45,15 @@ class SeriesLine(Archetype): # Set up plot styling: # They are logged as static as they don't change over time and apply to all timelines. # Log two lines series under a shared root so that they show in the same plot by default. - rr.log("trig/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)", width=2), static=True) - rr.log("trig/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)", width=4), static=True) + rr.log("trig/sin", rr.SeriesLines(colors=[255, 0, 0], names="sin(0.01t)", widths=2), static=True) + rr.log("trig/cos", rr.SeriesLines(colors=[0, 255, 0], names="cos(0.01t)", widths=4), static=True) # Log the data on a timeline called "step". for t in range(int(tau * 2 * 100.0)): rr.set_time("step", sequence=t) - rr.log("trig/sin", rr.Scalar(sin(float(t) / 100.0))) - rr.log("trig/cos", rr.Scalar(cos(float(t) / 100.0))) + rr.log("trig/sin", rr.Scalars(sin(float(t) / 100.0))) + rr.log("trig/cos", rr.Scalars(cos(float(t) / 100.0))) ```
@@ -125,6 +127,7 @@ def __attrs_clear__(self) -> None: ) @classmethod + @deprecated("""Use `SeriesLines` instead.""") def _clear(cls) -> SeriesLine: """Produce an empty SeriesLine, bypassing `__init__`.""" inst = cls.__new__(cls) @@ -132,6 +135,7 @@ def _clear(cls) -> SeriesLine: return inst @classmethod + @deprecated("""Use `SeriesLines` instead.""") def from_fields( cls, *, @@ -197,6 +201,7 @@ def cleared(cls) -> SeriesLine: return cls.from_fields(clear_unset=True) @classmethod + @deprecated("""Use `SeriesLines` instead.""") def columns( cls, *, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/series_lines.py b/rerun_py/rerun_sdk/rerun/archetypes/series_lines.py new file mode 100644 index 000000000000..bd749f3562b1 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/archetypes/series_lines.py @@ -0,0 +1,383 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/archetypes/series_lines.fbs". + +# You can extend this class by creating a "SeriesLinesExt" class in "series_lines_ext.py". + +from __future__ import annotations + +from typing import Any + +import numpy as np +import pyarrow as pa +from attrs import define, field + +from .. import components, datatypes +from .._baseclasses import ( + Archetype, + ComponentColumnList, +) +from ..error_utils import catch_and_log_exceptions + +__all__ = ["SeriesLines"] + + +@define(str=False, repr=False, init=False) +class SeriesLines(Archetype): + """ + **Archetype**: Define the style properties for one or more line series in a chart. + + This archetype only provides styling information. + Changes over time are supported for most but not all its fields (see respective fields for details), + it's generally recommended to log this type as static. + + The underlying data needs to be logged to the same entity-path using [`archetypes.Scalars`][rerun.archetypes.Scalars]. + Dimensionality of the scalar arrays logged at each time point is assumed to be the same over time. + + Example + ------- + ### Line series: + ```python + from math import cos, sin, tau + + import rerun as rr + + rr.init("rerun_example_series_line_style", spawn=True) + + # Set up plot styling: + # They are logged as static as they don't change over time and apply to all timelines. + # Log two lines series under a shared root so that they show in the same plot by default. + rr.log("trig/sin", rr.SeriesLines(colors=[255, 0, 0], names="sin(0.01t)", widths=2), static=True) + rr.log("trig/cos", rr.SeriesLines(colors=[0, 255, 0], names="cos(0.01t)", widths=4), static=True) + + # Log the data on a timeline called "step". + for t in range(int(tau * 2 * 100.0)): + rr.set_time("step", sequence=t) + + rr.log("trig/sin", rr.Scalars(sin(float(t) / 100.0))) + rr.log("trig/cos", rr.Scalars(cos(float(t) / 100.0))) + ``` +
+ + + + + + + +
+ + """ + + def __init__( + self: Any, + *, + colors: datatypes.Rgba32ArrayLike | None = None, + widths: datatypes.Float32ArrayLike | None = None, + names: datatypes.Utf8ArrayLike | None = None, + visible_series: datatypes.BoolArrayLike | None = None, + aggregation_policy: components.AggregationPolicyLike | None = None, + ) -> None: + """ + Create a new instance of the SeriesLines archetype. + + Parameters + ---------- + colors: + Color for the corresponding series. + + May change over time, but can cause discontinuities in the line. + widths: + Stroke width for the corresponding series. + + May change over time, but can cause discontinuities in the line. + names: + Display name of the series. + + Used in the legend. Expected to be unchanging over time. + visible_series: + Which lines are visible. + + If not set, all line series on this entity are visible. + Unlike with the regular visibility property of the entire entity, any series that is hidden + via this property will still be visible in the legend. + + May change over time, but can cause discontinuities in the line. + aggregation_policy: + Configures the zoom-dependent scalar aggregation. + + This is done only if steps on the X axis go below a single pixel, + i.e. a single pixel covers more than one tick worth of data. It can greatly improve performance + (and readability) in such situations as it prevents overdraw. + + Expected to be unchanging over time. + + """ + + # You can define your own __init__ function as a member of SeriesLinesExt in series_lines_ext.py + with catch_and_log_exceptions(context=self.__class__.__name__): + self.__attrs_init__( + colors=colors, + widths=widths, + names=names, + visible_series=visible_series, + aggregation_policy=aggregation_policy, + ) + return + self.__attrs_clear__() + + def __attrs_clear__(self) -> None: + """Convenience method for calling `__attrs_init__` with all `None`s.""" + self.__attrs_init__( + colors=None, + widths=None, + names=None, + visible_series=None, + aggregation_policy=None, + ) + + @classmethod + def _clear(cls) -> SeriesLines: + """Produce an empty SeriesLines, bypassing `__init__`.""" + inst = cls.__new__(cls) + inst.__attrs_clear__() + return inst + + @classmethod + def from_fields( + cls, + *, + clear_unset: bool = False, + colors: datatypes.Rgba32ArrayLike | None = None, + widths: datatypes.Float32ArrayLike | None = None, + names: datatypes.Utf8ArrayLike | None = None, + visible_series: datatypes.BoolArrayLike | None = None, + aggregation_policy: components.AggregationPolicyLike | None = None, + ) -> SeriesLines: + """ + Update only some specific fields of a `SeriesLines`. + + Parameters + ---------- + clear_unset: + If true, all unspecified fields will be explicitly cleared. + colors: + Color for the corresponding series. + + May change over time, but can cause discontinuities in the line. + widths: + Stroke width for the corresponding series. + + May change over time, but can cause discontinuities in the line. + names: + Display name of the series. + + Used in the legend. Expected to be unchanging over time. + visible_series: + Which lines are visible. + + If not set, all line series on this entity are visible. + Unlike with the regular visibility property of the entire entity, any series that is hidden + via this property will still be visible in the legend. + + May change over time, but can cause discontinuities in the line. + aggregation_policy: + Configures the zoom-dependent scalar aggregation. + + This is done only if steps on the X axis go below a single pixel, + i.e. a single pixel covers more than one tick worth of data. It can greatly improve performance + (and readability) in such situations as it prevents overdraw. + + Expected to be unchanging over time. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "colors": colors, + "widths": widths, + "names": names, + "visible_series": visible_series, + "aggregation_policy": aggregation_policy, + } + + if clear_unset: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def cleared(cls) -> SeriesLines: + """Clear all the fields of a `SeriesLines`.""" + return cls.from_fields(clear_unset=True) + + @classmethod + def columns( + cls, + *, + colors: datatypes.Rgba32ArrayLike | None = None, + widths: datatypes.Float32ArrayLike | None = None, + names: datatypes.Utf8ArrayLike | None = None, + visible_series: datatypes.BoolArrayLike | None = None, + aggregation_policy: components.AggregationPolicyArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + colors: + Color for the corresponding series. + + May change over time, but can cause discontinuities in the line. + widths: + Stroke width for the corresponding series. + + May change over time, but can cause discontinuities in the line. + names: + Display name of the series. + + Used in the legend. Expected to be unchanging over time. + visible_series: + Which lines are visible. + + If not set, all line series on this entity are visible. + Unlike with the regular visibility property of the entire entity, any series that is hidden + via this property will still be visible in the legend. + + May change over time, but can cause discontinuities in the line. + aggregation_policy: + Configures the zoom-dependent scalar aggregation. + + This is done only if steps on the X axis go below a single pixel, + i.e. a single pixel covers more than one tick worth of data. It can greatly improve performance + (and readability) in such situations as it prevents overdraw. + + Expected to be unchanging over time. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + colors=colors, + widths=widths, + names=names, + visible_series=visible_series, + aggregation_policy=aggregation_policy, + ) + + batches = inst.as_component_batches(include_indicators=False) + if len(batches) == 0: + return ComponentColumnList([]) + + kwargs = { + "colors": colors, + "widths": widths, + "names": names, + "visible_series": visible_series, + "aggregation_policy": aggregation_policy, + } + columns = [] + + for batch in batches: + arrow_array = batch.as_arrow_array() + + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): + param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] + shape = np.shape(param) # type: ignore[arg-type] + + if pa.types.is_fixed_size_list(arrow_array.type) and len(shape) <= 2: + # If shape length is 2 or less, we have `num_rows` single element batches (each element is a fixed sized list). + # `shape[1]` should be the length of the fixed sized list. + # (This should have been already validated by conversion to the arrow_array) + batch_length = 1 + else: + batch_length = shape[1] if len(shape) > 1 else 1 # type: ignore[redundant-expr,misc] + + num_rows = shape[0] if len(shape) >= 1 else 1 # type: ignore[redundant-expr,misc] + sizes = batch_length * np.ones(num_rows) + else: + # For non-primitive types, default to partitioning each element separately. + sizes = np.ones(len(arrow_array)) + + columns.append(batch.partition(sizes)) + + indicator_column = cls.indicator().partition(np.zeros(len(sizes))) + return ComponentColumnList([indicator_column] + columns) + + colors: components.ColorBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.ColorBatch._converter, # type: ignore[misc] + ) + # Color for the corresponding series. + # + # May change over time, but can cause discontinuities in the line. + # + # (Docstring intentionally commented out to hide this field from the docs) + + widths: components.StrokeWidthBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.StrokeWidthBatch._converter, # type: ignore[misc] + ) + # Stroke width for the corresponding series. + # + # May change over time, but can cause discontinuities in the line. + # + # (Docstring intentionally commented out to hide this field from the docs) + + names: components.NameBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.NameBatch._converter, # type: ignore[misc] + ) + # Display name of the series. + # + # Used in the legend. Expected to be unchanging over time. + # + # (Docstring intentionally commented out to hide this field from the docs) + + visible_series: components.SeriesVisibleBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.SeriesVisibleBatch._converter, # type: ignore[misc] + ) + # Which lines are visible. + # + # If not set, all line series on this entity are visible. + # Unlike with the regular visibility property of the entire entity, any series that is hidden + # via this property will still be visible in the legend. + # + # May change over time, but can cause discontinuities in the line. + # + # (Docstring intentionally commented out to hide this field from the docs) + + aggregation_policy: components.AggregationPolicyBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.AggregationPolicyBatch._converter, # type: ignore[misc] + ) + # Configures the zoom-dependent scalar aggregation. + # + # This is done only if steps on the X axis go below a single pixel, + # i.e. a single pixel covers more than one tick worth of data. It can greatly improve performance + # (and readability) in such situations as it prevents overdraw. + # + # Expected to be unchanging over time. + # + # (Docstring intentionally commented out to hide this field from the docs) + + __str__ = Archetype.__str__ + __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/series_point.py b/rerun_py/rerun_sdk/rerun/archetypes/series_point.py index 9a9b895465d4..2dc97ad4dce2 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/series_point.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/series_point.py @@ -10,6 +10,7 @@ import numpy as np import pyarrow as pa from attrs import define, field +from typing_extensions import deprecated # type: ignore[misc, unused-ignore] from .. import components, datatypes from .._baseclasses import ( @@ -21,6 +22,7 @@ __all__ = ["SeriesPoint"] +@deprecated("""Use `SeriesPoints` instead.""") @define(str=False, repr=False, init=False) class SeriesPoint(Archetype): """ @@ -28,7 +30,7 @@ class SeriesPoint(Archetype): This archetype only provides styling information and should be logged as static when possible. The underlying data needs to be logged to the same entity-path using - [`archetypes.Scalar`][rerun.archetypes.Scalar]. + [`archetypes.Scalars`][rerun.archetypes.Scalars]. Example ------- @@ -45,31 +47,32 @@ class SeriesPoint(Archetype): # Log two point series under a shared root so that they show in the same plot by default. rr.log( "trig/sin", - rr.SeriesPoint( - color=[255, 0, 0], - name="sin(0.01t)", - marker="circle", - marker_size=4, + rr.SeriesPoints( + colors=[255, 0, 0], + names="sin(0.01t)", + markers="circle", + marker_sizes=4, ), static=True, ) rr.log( "trig/cos", - rr.SeriesPoint( - color=[0, 255, 0], - name="cos(0.01t)", - marker="cross", - marker_size=2, + rr.SeriesPoints( + colors=[0, 255, 0], + names="cos(0.01t)", + markers="cross", + marker_sizes=2, ), static=True, ) + # Log the data on a timeline called "step". for t in range(int(tau * 2 * 10.0)): rr.set_time("step", sequence=t) - rr.log("trig/sin", rr.Scalar(sin(float(t) / 10.0))) - rr.log("trig/cos", rr.Scalar(cos(float(t) / 10.0))) + rr.log("trig/sin", rr.Scalars(sin(float(t) / 10.0))) + rr.log("trig/cos", rr.Scalars(cos(float(t) / 10.0))) ```
@@ -135,6 +138,7 @@ def __attrs_clear__(self) -> None: ) @classmethod + @deprecated("""Use `SeriesPoints` instead.""") def _clear(cls) -> SeriesPoint: """Produce an empty SeriesPoint, bypassing `__init__`.""" inst = cls.__new__(cls) @@ -142,6 +146,7 @@ def _clear(cls) -> SeriesPoint: return inst @classmethod + @deprecated("""Use `SeriesPoints` instead.""") def from_fields( cls, *, @@ -203,6 +208,7 @@ def cleared(cls) -> SeriesPoint: return cls.from_fields(clear_unset=True) @classmethod + @deprecated("""Use `SeriesPoints` instead.""") def columns( cls, *, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/series_points.py b/rerun_py/rerun_sdk/rerun/archetypes/series_points.py new file mode 100644 index 000000000000..fb8acb7f007c --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/archetypes/series_points.py @@ -0,0 +1,382 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/archetypes/series_points.fbs". + +# You can extend this class by creating a "SeriesPointsExt" class in "series_points_ext.py". + +from __future__ import annotations + +from typing import Any + +import numpy as np +import pyarrow as pa +from attrs import define, field + +from .. import components, datatypes +from .._baseclasses import ( + Archetype, + ComponentColumnList, +) +from ..error_utils import catch_and_log_exceptions + +__all__ = ["SeriesPoints"] + + +@define(str=False, repr=False, init=False) +class SeriesPoints(Archetype): + """ + **Archetype**: Define the style properties for one or more point series (scatter plot) in a chart. + + This archetype only provides styling information. + Changes over time are supported for most but not all its fields (see respective fields for details), + it's generally recommended to log this type as static. + + The underlying data needs to be logged to the same entity-path using [`archetypes.Scalars`][rerun.archetypes.Scalars]. + Dimensionality of the scalar arrays logged at each time point is assumed to be the same over time. + + Example + ------- + ### Point series: + ```python + from math import cos, sin, tau + + import rerun as rr + + rr.init("rerun_example_series_point_style", spawn=True) + + # Set up plot styling: + # They are logged as static as they don't change over time and apply to all timelines. + # Log two point series under a shared root so that they show in the same plot by default. + rr.log( + "trig/sin", + rr.SeriesPoints( + colors=[255, 0, 0], + names="sin(0.01t)", + markers="circle", + marker_sizes=4, + ), + static=True, + ) + rr.log( + "trig/cos", + rr.SeriesPoints( + colors=[0, 255, 0], + names="cos(0.01t)", + markers="cross", + marker_sizes=2, + ), + static=True, + ) + + + # Log the data on a timeline called "step". + for t in range(int(tau * 2 * 10.0)): + rr.set_time("step", sequence=t) + + rr.log("trig/sin", rr.Scalars(sin(float(t) / 10.0))) + rr.log("trig/cos", rr.Scalars(cos(float(t) / 10.0))) + ``` +
+ + + + + + + +
+ + """ + + def __init__( + self: Any, + *, + colors: datatypes.Rgba32ArrayLike | None = None, + markers: components.MarkerShapeArrayLike | None = None, + names: datatypes.Utf8ArrayLike | None = None, + visible_series: datatypes.BoolArrayLike | None = None, + marker_sizes: datatypes.Float32ArrayLike | None = None, + ) -> None: + """ + Create a new instance of the SeriesPoints archetype. + + Parameters + ---------- + colors: + Color for the corresponding series. + + May change over time, but can cause discontinuities in the line. + markers: + What shape to use to represent the point + + May change over time. + names: + Display name of the series. + + Used in the legend. Expected to be unchanging over time. + visible_series: + Which lines are visible. + + If not set, all line series on this entity are visible. + Unlike with the regular visibility property of the entire entity, any series that is hidden + via this property will still be visible in the legend. + + May change over time. + marker_sizes: + Sizes of the markers. + + May change over time. + + """ + + # You can define your own __init__ function as a member of SeriesPointsExt in series_points_ext.py + with catch_and_log_exceptions(context=self.__class__.__name__): + self.__attrs_init__( + colors=colors, markers=markers, names=names, visible_series=visible_series, marker_sizes=marker_sizes + ) + return + self.__attrs_clear__() + + def __attrs_clear__(self) -> None: + """Convenience method for calling `__attrs_init__` with all `None`s.""" + self.__attrs_init__( + colors=None, + markers=None, + names=None, + visible_series=None, + marker_sizes=None, + ) + + @classmethod + def _clear(cls) -> SeriesPoints: + """Produce an empty SeriesPoints, bypassing `__init__`.""" + inst = cls.__new__(cls) + inst.__attrs_clear__() + return inst + + @classmethod + def from_fields( + cls, + *, + clear_unset: bool = False, + colors: datatypes.Rgba32ArrayLike | None = None, + markers: components.MarkerShapeArrayLike | None = None, + names: datatypes.Utf8ArrayLike | None = None, + visible_series: datatypes.BoolArrayLike | None = None, + marker_sizes: datatypes.Float32ArrayLike | None = None, + ) -> SeriesPoints: + """ + Update only some specific fields of a `SeriesPoints`. + + Parameters + ---------- + clear_unset: + If true, all unspecified fields will be explicitly cleared. + colors: + Color for the corresponding series. + + May change over time, but can cause discontinuities in the line. + markers: + What shape to use to represent the point + + May change over time. + names: + Display name of the series. + + Used in the legend. Expected to be unchanging over time. + visible_series: + Which lines are visible. + + If not set, all line series on this entity are visible. + Unlike with the regular visibility property of the entire entity, any series that is hidden + via this property will still be visible in the legend. + + May change over time. + marker_sizes: + Sizes of the markers. + + May change over time. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "colors": colors, + "markers": markers, + "names": names, + "visible_series": visible_series, + "marker_sizes": marker_sizes, + } + + if clear_unset: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def cleared(cls) -> SeriesPoints: + """Clear all the fields of a `SeriesPoints`.""" + return cls.from_fields(clear_unset=True) + + @classmethod + def columns( + cls, + *, + colors: datatypes.Rgba32ArrayLike | None = None, + markers: components.MarkerShapeArrayLike | None = None, + names: datatypes.Utf8ArrayLike | None = None, + visible_series: datatypes.BoolArrayLike | None = None, + marker_sizes: datatypes.Float32ArrayLike | None = None, + ) -> ComponentColumnList: + """ + Construct a new column-oriented component bundle. + + This makes it possible to use `rr.send_columns` to send columnar data directly into Rerun. + + The returned columns will be partitioned into unit-length sub-batches by default. + Use `ComponentColumnList.partition` to repartition the data as needed. + + Parameters + ---------- + colors: + Color for the corresponding series. + + May change over time, but can cause discontinuities in the line. + markers: + What shape to use to represent the point + + May change over time. + names: + Display name of the series. + + Used in the legend. Expected to be unchanging over time. + visible_series: + Which lines are visible. + + If not set, all line series on this entity are visible. + Unlike with the regular visibility property of the entire entity, any series that is hidden + via this property will still be visible in the legend. + + May change over time. + marker_sizes: + Sizes of the markers. + + May change over time. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + inst.__attrs_init__( + colors=colors, + markers=markers, + names=names, + visible_series=visible_series, + marker_sizes=marker_sizes, + ) + + batches = inst.as_component_batches(include_indicators=False) + if len(batches) == 0: + return ComponentColumnList([]) + + kwargs = { + "colors": colors, + "markers": markers, + "names": names, + "visible_series": visible_series, + "marker_sizes": marker_sizes, + } + columns = [] + + for batch in batches: + arrow_array = batch.as_arrow_array() + + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): + param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] + shape = np.shape(param) # type: ignore[arg-type] + + if pa.types.is_fixed_size_list(arrow_array.type) and len(shape) <= 2: + # If shape length is 2 or less, we have `num_rows` single element batches (each element is a fixed sized list). + # `shape[1]` should be the length of the fixed sized list. + # (This should have been already validated by conversion to the arrow_array) + batch_length = 1 + else: + batch_length = shape[1] if len(shape) > 1 else 1 # type: ignore[redundant-expr,misc] + + num_rows = shape[0] if len(shape) >= 1 else 1 # type: ignore[redundant-expr,misc] + sizes = batch_length * np.ones(num_rows) + else: + # For non-primitive types, default to partitioning each element separately. + sizes = np.ones(len(arrow_array)) + + columns.append(batch.partition(sizes)) + + indicator_column = cls.indicator().partition(np.zeros(len(sizes))) + return ComponentColumnList([indicator_column] + columns) + + colors: components.ColorBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.ColorBatch._converter, # type: ignore[misc] + ) + # Color for the corresponding series. + # + # May change over time, but can cause discontinuities in the line. + # + # (Docstring intentionally commented out to hide this field from the docs) + + markers: components.MarkerShapeBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.MarkerShapeBatch._converter, # type: ignore[misc] + ) + # What shape to use to represent the point + # + # May change over time. + # + # (Docstring intentionally commented out to hide this field from the docs) + + names: components.NameBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.NameBatch._converter, # type: ignore[misc] + ) + # Display name of the series. + # + # Used in the legend. Expected to be unchanging over time. + # + # (Docstring intentionally commented out to hide this field from the docs) + + visible_series: components.SeriesVisibleBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.SeriesVisibleBatch._converter, # type: ignore[misc] + ) + # Which lines are visible. + # + # If not set, all line series on this entity are visible. + # Unlike with the regular visibility property of the entire entity, any series that is hidden + # via this property will still be visible in the legend. + # + # May change over time. + # + # (Docstring intentionally commented out to hide this field from the docs) + + marker_sizes: components.MarkerSizeBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.MarkerSizeBatch._converter, # type: ignore[misc] + ) + # Sizes of the markers. + # + # May change over time. + # + # (Docstring intentionally commented out to hide this field from the docs) + + __str__ = Archetype.__str__ + __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/dataframe_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/dataframe_view.py index 5c6fbae81295..11d6c6b0d8d5 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/dataframe_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/dataframe_view.py @@ -39,12 +39,12 @@ class DataframeView(View): # Log some data. for t in range(int(math.pi * 4 * 100.0)): rr.set_time("t", duration=t) - rr.log("trig/sin", rr.Scalar(math.sin(float(t) / 100.0))) - rr.log("trig/cos", rr.Scalar(math.cos(float(t) / 100.0))) + rr.log("trig/sin", rr.Scalars(math.sin(float(t) / 100.0))) + rr.log("trig/cos", rr.Scalars(math.cos(float(t) / 100.0))) # some sparse data if t % 5 == 0: - rr.log("trig/tan_sparse", rr.Scalar(math.tan(float(t) / 100.0))) + rr.log("trig/tan_sparse", rr.Scalars(math.tan(float(t) / 100.0))) # Create a Dataframe View blueprint = rrb.Blueprint( diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/time_series_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/time_series_view.py index e75a5eaf0eee..d4766cea5239 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/time_series_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/time_series_view.py @@ -21,7 +21,7 @@ class TimeSeriesView(View): """ - **View**: A time series view for scalars over time, for use with [`archetypes.Scalar`][rerun.archetypes.Scalar]. + **View**: A time series view for scalars over time, for use with [`archetypes.Scalars`][rerun.archetypes.Scalars]. Example ------- @@ -35,15 +35,15 @@ class TimeSeriesView(View): rr.init("rerun_example_timeseries", spawn=True) # Log some trigonometric functions - rr.log("trig/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)"), static=True) - rr.log("trig/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)"), static=True) - rr.log("trig/cos", rr.SeriesLine(color=[0, 0, 255], name="cos(0.01t) scaled"), static=True) + rr.log("trig/sin", rr.SeriesLines(colors=[255, 0, 0], names="sin(0.01t)"), static=True) + rr.log("trig/cos", rr.SeriesLines(colors=[0, 255, 0], names="cos(0.01t)"), static=True) + rr.log("trig/cos_scaled", rr.SeriesLines(colors=[0, 0, 255], names="cos(0.01t) scaled"), static=True) for t in range(int(math.pi * 4 * 100.0)): rr.set_time("timeline0", sequence=t) rr.set_time("timeline1", duration=t) - rr.log("trig/sin", rr.Scalar(math.sin(float(t) / 100.0))) - rr.log("trig/cos", rr.Scalar(math.cos(float(t) / 100.0))) - rr.log("trig/cos_scaled", rr.Scalar(math.cos(float(t) / 100.0) * 2.0)) + rr.log("trig/sin", rr.Scalars(math.sin(float(t) / 100.0))) + rr.log("trig/cos", rr.Scalars(math.cos(float(t) / 100.0))) + rr.log("trig/cos_scaled", rr.Scalars(math.cos(float(t) / 100.0) * 2.0)) # Create a TimeSeries View blueprint = rrb.Blueprint( diff --git a/rerun_py/rerun_sdk/rerun/blueprint/visualizers.py b/rerun_py/rerun_sdk/rerun/blueprint/visualizers.py index 15c54ab4c21f..9bb87c816f70 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/visualizers.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/visualizers.py @@ -21,5 +21,5 @@ TextDocument = "TextDocument" TextLog = "TextLog" SegmentationImage = "SegmentationImage" -SeriesLine = "SeriesLine" -SeriesPoint = "SeriesPoint" +SeriesLines = "SeriesLines" +SeriesPoints = "SeriesPoints" diff --git a/rerun_py/tests/unit/test_scalar.py b/rerun_py/tests/unit/test_scalars.py similarity index 87% rename from rerun_py/tests/unit/test_scalar.py rename to rerun_py/tests/unit/test_scalars.py index 446c712fb671..275afdbb699e 100644 --- a/rerun_py/tests/unit/test_scalar.py +++ b/rerun_py/tests/unit/test_scalars.py @@ -1,7 +1,7 @@ from __future__ import annotations import numpy as np -from rerun.archetypes import Scalar +from rerun.archetypes import Scalars from rerun.datatypes import Float64ArrayLike CASES: list[tuple[Float64ArrayLike, Float64ArrayLike]] = [ @@ -31,7 +31,7 @@ ] -def test_scalar_columns() -> None: +def test_scalars_columns() -> None: for input, expected in CASES: - data = [*Scalar.columns(scalar=input)] + data = [*Scalars.columns(scalars=input)] assert data[1].as_arrow_array().to_pylist() == expected diff --git a/rerun_py/tests/unit/test_series_styles.py b/rerun_py/tests/unit/test_series_styles.py index 0ed54b7394e2..ca3ec698ea04 100644 --- a/rerun_py/tests/unit/test_series_styles.py +++ b/rerun_py/tests/unit/test_series_styles.py @@ -1,6 +1,6 @@ from __future__ import annotations -from rerun.archetypes import SeriesLine, SeriesPoint +from rerun.archetypes import SeriesLines, SeriesPoints from rerun.components import ( Color, ColorBatch, @@ -17,45 +17,45 @@ def test_line_series() -> None: inputs = [ - SeriesLine(), - SeriesLine(color=[255, 0, 0]), - SeriesLine(color=0xFF0000FF), - SeriesLine(width=2), - SeriesLine(width=2.0), - SeriesLine(name="my plot"), - SeriesLine(color=[255, 0, 0], width=2, name="my plot"), + SeriesLines(), + SeriesLines(colors=[255, 0, 0]), + SeriesLines(colors=0xFF0000FF), + SeriesLines(widths=2), + SeriesLines(widths=2.0), + SeriesLines(names="my plot"), + SeriesLines(colors=[255, 0, 0], widths=2, names="my plot"), ] for input in inputs: - if input.color is not None: - assert input.color == ColorBatch._converter([Color([255, 0, 0])]) - if input.width is not None: - assert input.width == StrokeWidthBatch._converter([StrokeWidth(2.0)]) - if input.name is not None: - assert input.name == NameBatch._converter([Name("my plot")]) + if input.colors is not None: + assert input.colors == ColorBatch._converter([Color([255, 0, 0])]) + if input.widths is not None: + assert input.widths == StrokeWidthBatch._converter([StrokeWidth(2.0)]) + if input.names is not None: + assert input.names == NameBatch._converter([Name("my plot")]) def test_point_series() -> None: inputs = [ - SeriesPoint(), - SeriesPoint(color=[255, 0, 0]), - SeriesPoint(color=0xFF0000FF), - SeriesPoint(marker_size=2), - SeriesPoint(marker=MarkerShape.Diamond), - SeriesPoint(marker="diamond"), - SeriesPoint(name="my plot"), - SeriesPoint(color=[255, 0, 0], marker_size=2, marker="diamond", name="my plot"), + SeriesPoints(), + SeriesPoints(colors=[255, 0, 0]), + SeriesPoints(colors=0xFF0000FF), + SeriesPoints(marker_sizes=2), + SeriesPoints(markers=MarkerShape.Diamond), + SeriesPoints(markers="diamond"), + SeriesPoints(names="my plot"), + SeriesPoints(colors=[255, 0, 0], marker_sizes=2, markers="diamond", names="my plot"), ] for input in inputs: - if input.color is not None: - assert input.color == ColorBatch._converter([Color([255, 0, 0])]) - if input.marker_size is not None: - assert input.marker_size == MarkerSizeBatch._converter([MarkerSize(2.0)]) - if input.marker is not None: - assert input.marker == MarkerShapeBatch._converter([MarkerShape.Diamond]) - if input.name is not None: - assert input.name == NameBatch._converter([Name("my plot")]) + if input.colors is not None: + assert input.colors == ColorBatch._converter([Color([255, 0, 0])]) + if input.marker_sizes is not None: + assert input.marker_sizes == MarkerSizeBatch._converter([MarkerSize(2.0)]) + if input.markers is not None: + assert input.markers == MarkerShapeBatch._converter([MarkerShape.Diamond]) + if input.names is not None: + assert input.names == NameBatch._converter([Name("my plot")]) if __name__ == "__main__": diff --git a/tests/cpp/plot_dashboard_stress/main.cpp b/tests/cpp/plot_dashboard_stress/main.cpp index 60cc229d2952..4e9f8c63ecc8 100644 --- a/tests/cpp/plot_dashboard_stress/main.cpp +++ b/tests/cpp/plot_dashboard_stress/main.cpp @@ -189,15 +189,13 @@ int main(int argc, char** argv) { rec.send_columns( path, *time_column, - rerun::Scalar::update_fields() - .with_many_scalar(rerun::borrow( - series_values.data() + time_step, - *temporal_batch_size - )) + rerun::Scalars( + rerun::borrow(series_values.data() + time_step, *temporal_batch_size) + ) .columns() ); } else { - rec.log(path, rerun::Scalar(series_values[time_step])); + rec.log(path, rerun::Scalars(series_values[time_step])); } } } diff --git a/tests/python/chunk_zoo/chunk_zoo.py b/tests/python/chunk_zoo/chunk_zoo.py index 077bf6792135..e312219ddb37 100644 --- a/tests/python/chunk_zoo/chunk_zoo.py +++ b/tests/python/chunk_zoo/chunk_zoo.py @@ -143,12 +143,12 @@ def specimen_scalars_interlaced_in_two_chunks() -> None: rr.send_columns( "/scalars_interlaced_in_two_chunks", frame_times(0, 2, 5, 6, 8), - rr.Scalar.columns(scalar=[0, 2, 5, 6, 8]), + rr.Scalars.columns(scalars=[0, 2, 5, 6, 8]), ) rr.send_columns( "/scalars_interlaced_in_two_chunks", frame_times(1, 3, 7), - rr.Scalar.columns(scalar=[1, 3, 7]), + rr.Scalars.columns(scalars=[1, 3, 7]), ) diff --git a/tests/python/plot_dashboard_stress/main.py b/tests/python/plot_dashboard_stress/main.py index 219d018b7c84..61cb8b6a1e01 100755 --- a/tests/python/plot_dashboard_stress/main.py +++ b/tests/python/plot_dashboard_stress/main.py @@ -180,13 +180,13 @@ def main() -> None: for series_idx, series_path in enumerate(series_paths): if args.temporal_batch_size is None: value = values[index, plot_idx, series_idx] - rr.log(f"{plot_path}/{series_path}", rr.Scalar(value)) + rr.log(f"{plot_path}/{series_path}", rr.Scalars(value)) else: value_index = slice(index, index + args.temporal_batch_size) rr.send_columns( f"{plot_path}/{series_path}", indexes=[cast(rr.TimeColumn, time_column)], - columns=rr.Scalar.columns(scalar=values[value_index, plot_idx, series_idx]), + columns=rr.Scalars.columns(scalars=values[value_index, plot_idx, series_idx]), ) # Measure how long this took and how high the load was. diff --git a/tests/python/release_checklist/check_blueprint_overrides.py b/tests/python/release_checklist/check_blueprint_overrides.py index d5f414a6740f..24f8869b8531 100644 --- a/tests/python/release_checklist/check_blueprint_overrides.py +++ b/tests/python/release_checklist/check_blueprint_overrides.py @@ -29,10 +29,10 @@ def log_plots() -> None: rr.set_time("frame_nr", sequence=t) sin_of_t = sin(float(t) / 10.0) - rr.log("plots/sin", rr.Scalar(sin_of_t)) + rr.log("plots/sin", rr.Scalars(sin_of_t)) cos_of_t = cos(float(t) / 10.0) - rr.log("plots/cos", rr.Scalar(cos_of_t)) + rr.log("plots/cos", rr.Scalars(cos_of_t)) def run(args: Namespace) -> None: @@ -46,11 +46,11 @@ def run(args: Namespace) -> None: rrb.TextDocumentView(origin="readme", name="Instructions"), rrb.TimeSeriesView( name="Plots", - defaults=[rr.SeriesPoint.from_fields(color=[0, 0, 255])], + defaults=[rr.SeriesPoints.from_fields(colors=[0, 0, 255])], overrides={ "plots/cos": [ - rrb.VisualizerOverrides("SeriesPoint"), - rr.SeriesPoint.from_fields(color=[0, 255, 0], marker="cross"), + rrb.VisualizerOverrides("SeriesPoints"), + rr.SeriesPoints.from_fields(colors=[0, 255, 0], markers="cross"), ], }, ), diff --git a/tests/python/release_checklist/check_container_hierarchy.py b/tests/python/release_checklist/check_container_hierarchy.py index 8f4db9577ecb..bd053499b71c 100644 --- a/tests/python/release_checklist/check_container_hierarchy.py +++ b/tests/python/release_checklist/check_container_hierarchy.py @@ -75,17 +75,17 @@ def log_some_views() -> None: rr.log("points2d", rr.Points2D([[0, 0], [1, 1], [3, 2]], labels=["a", "b", "c"])) rr.log("points2d/bbx", rr.Boxes2D(centers=[1, 1], half_sizes=[3, 3])) - rr.log("plots/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)"), static=True) - rr.log("plots/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)"), static=True) + rr.log("plots/sin", rr.SeriesLines(colors=[255, 0, 0], names="sin(0.01t)"), static=True) + rr.log("plots/cos", rr.SeriesLines(colors=[0, 255, 0], names="cos(0.01t)"), static=True) for t in range(int(tau * 2 * 10.0)): rr.set_time("frame_nr", sequence=t) sin_of_t = sin(float(t) / 10.0) - rr.log("plots/sin", rr.Scalar(sin_of_t)) + rr.log("plots/sin", rr.Scalars(sin_of_t)) cos_of_t = cos(float(t) / 10.0) - rr.log("plots/cos", rr.Scalar(cos_of_t)) + rr.log("plots/cos", rr.Scalars(cos_of_t)) def run(args: Namespace) -> None: diff --git a/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py b/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py index 4a940b26db69..bcbba7c66a4b 100644 --- a/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py +++ b/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py @@ -57,7 +57,7 @@ def log_some_views() -> None: for i in range(10): rr.set_time("frame_nr", sequence=i) - rr.log("timeseries", rr.Scalar(random.randint(0, 100))) + rr.log("timeseries", rr.Scalars(random.randint(0, 100))) def run(args: Namespace) -> None: diff --git a/tests/python/release_checklist/check_drag_and_drop_selection.py b/tests/python/release_checklist/check_drag_and_drop_selection.py index 28f81875fac1..921d05ebac5e 100644 --- a/tests/python/release_checklist/check_drag_and_drop_selection.py +++ b/tests/python/release_checklist/check_drag_and_drop_selection.py @@ -59,7 +59,7 @@ def log_some_scalar_entities() -> None: time_column = rr.TimeColumn("frame", sequence=times) for path, curve in curves: - rr.send_columns(path, indexes=[time_column], columns=rr.Scalar.columns(scalar=curve)) + rr.send_columns(path, indexes=[time_column], columns=rr.Scalars.columns(scalars=curve)) def run(args: Namespace) -> None: diff --git a/tests/python/release_checklist/check_entity_drag_and_drop.py b/tests/python/release_checklist/check_entity_drag_and_drop.py index 750581ec75c5..6b1b39bae089 100644 --- a/tests/python/release_checklist/check_entity_drag_and_drop.py +++ b/tests/python/release_checklist/check_entity_drag_and_drop.py @@ -75,7 +75,7 @@ def log_some_scalar_entities() -> None: time_column = rr.TimeColumn("frame", sequence=times) for path, curve in curves: - rr.send_columns(path, indexes=[time_column], columns=rr.Scalar.columns(scalar=curve)) + rr.send_columns(path, indexes=[time_column], columns=rr.Scalars.columns(scalars=curve)) def run(args: Namespace) -> None: diff --git a/tests/python/release_checklist/check_hover_select_reset.py b/tests/python/release_checklist/check_hover_select_reset.py index 8bf9f3e7752a..c3b2cd196697 100644 --- a/tests/python/release_checklist/check_hover_select_reset.py +++ b/tests/python/release_checklist/check_hover_select_reset.py @@ -51,16 +51,16 @@ def log_readme() -> None: def log_plots() -> None: from math import cos, sin, tau - rr.log("plots/cos", rr.SeriesPoint()) + rr.log("plots/cos", rr.SeriesPoints()) for t in range(int(tau * 2 * 10.0)): rr.set_time("frame_nr", sequence=t) sin_of_t = sin(float(t) / 10.0) - rr.log("plots/sin", rr.Scalar(sin_of_t)) + rr.log("plots/sin", rr.Scalars(sin_of_t)) cos_of_t = cos(float(t) / 10.0) - rr.log("plots/cos", rr.Scalar(cos_of_t)) + rr.log("plots/cos", rr.Scalars(cos_of_t)) def log_points_3d() -> None: diff --git a/tests/python/release_checklist/check_multi_entity_drag_and_drop.py b/tests/python/release_checklist/check_multi_entity_drag_and_drop.py index 0a4d60caf6ef..71b9ea6e722d 100644 --- a/tests/python/release_checklist/check_multi_entity_drag_and_drop.py +++ b/tests/python/release_checklist/check_multi_entity_drag_and_drop.py @@ -40,7 +40,7 @@ def log_some_scalar_entities() -> None: time_column = rr.TimeColumn("frame", sequence=times) for path, curve in curves: - rr.send_columns(path, indexes=[time_column], columns=rr.Scalar.columns(scalar=curve)) + rr.send_columns(path, indexes=[time_column], columns=rr.Scalars.columns(scalars=curve)) def run(args: Namespace) -> None: diff --git a/tests/python/release_checklist/check_parallelism_caching_reentrancy.py b/tests/python/release_checklist/check_parallelism_caching_reentrancy.py index 6f67d031672c..a647946401d1 100644 --- a/tests/python/release_checklist/check_parallelism_caching_reentrancy.py +++ b/tests/python/release_checklist/check_parallelism_caching_reentrancy.py @@ -84,17 +84,17 @@ def log_text_logs() -> None: def log_plots() -> None: from math import cos, sin, tau - rr.log("plots/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)"), static=True) - rr.log("plots/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)"), static=True) + rr.log("plots/sin", rr.SeriesLines(colors=[255, 0, 0], names="sin(0.01t)"), static=True) + rr.log("plots/cos", rr.SeriesLines(colors=[0, 255, 0], names="cos(0.01t)"), static=True) for t in range(int(tau * 2 * 10.0)): rr.set_time("frame_nr", sequence=t) sin_of_t = sin(float(t) / 10.0) - rr.log("plots/sin", rr.Scalar(sin_of_t)) + rr.log("plots/sin", rr.Scalars(sin_of_t)) cos_of_t = cos(float(t) / 10.0) - rr.log("plots/cos", rr.Scalar(cos_of_t)) + rr.log("plots/cos", rr.Scalars(cos_of_t)) def log_spatial() -> None: diff --git a/tests/python/release_checklist/check_plot_overrides.py b/tests/python/release_checklist/check_plot_overrides.py index 8e023262ea37..26a3deeaa00b 100644 --- a/tests/python/release_checklist/check_plot_overrides.py +++ b/tests/python/release_checklist/check_plot_overrides.py @@ -43,17 +43,17 @@ def log_readme() -> None: def log_plots() -> None: from math import cos, sin, tau - rr.log("plots/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)"), static=True) - rr.log("plots/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)"), static=True) + rr.log("plots/sin", rr.SeriesLines(colors=[255, 0, 0], names="sin(0.01t)"), static=True) + rr.log("plots/cos", rr.SeriesLines(colors=[0, 255, 0], names="cos(0.01t)"), static=True) for t in range(int(tau * 2 * 10.0)): rr.set_time("frame_nr", sequence=t) sin_of_t = sin(float(t) / 10.0) - rr.log("plots/sin", rr.Scalar(sin_of_t)) + rr.log("plots/sin", rr.Scalars(sin_of_t)) cos_of_t = cos(float(t) / 10.0) - rr.log("plots/cos", rr.Scalar(cos_of_t)) + rr.log("plots/cos", rr.Scalars(cos_of_t)) def run(args: Namespace) -> None: diff --git a/tests/python/release_checklist/check_rbl_import.py b/tests/python/release_checklist/check_rbl_import.py index f22870249cff..e87db8c51759 100644 --- a/tests/python/release_checklist/check_rbl_import.py +++ b/tests/python/release_checklist/check_rbl_import.py @@ -54,17 +54,19 @@ def lerp(a, b, t): # type: ignore[no-untyped-def] sin_of_t = sin(float(t) / 100.0) rr.log( "trig/sin", - rr.Scalar(sin_of_t), - rr.SeriesLine(width=5, color=lerp(np.array([1.0, 0, 0]), np.array([1.0, 1.0, 0]), (sin_of_t + 1.0) * 0.5)), + rr.Scalars(sin_of_t), + rr.SeriesLines( + widths=5, colors=lerp(np.array([1.0, 0, 0]), np.array([1.0, 1.0, 0]), (sin_of_t + 1.0) * 0.5) + ), ) cos_of_t = cos(float(t) / 100.0) rr.log( "trig/cos", - rr.Scalar(cos_of_t), - rr.SeriesLine( - width=5, - color=lerp(np.array([0.0, 1.0, 1.0]), np.array([0.0, 0.0, 1.0]), (cos_of_t + 1.0) * 0.5), + rr.Scalars(cos_of_t), + rr.SeriesLines( + widths=5, + colors=lerp(np.array([0.0, 1.0, 1.0]), np.array([0.0, 0.0, 1.0]), (cos_of_t + 1.0) * 0.5), ), ) diff --git a/tests/python/visible_history_playground/main.py b/tests/python/visible_history_playground/main.py index 30ad46ca9cb3..cc13450d41a6 100644 --- a/tests/python/visible_history_playground/main.py +++ b/tests/python/visible_history_playground/main.py @@ -58,7 +58,7 @@ rr.log("world/data/nested/transformed/point", rr.Boxes2D(centers=[0, 3], half_sizes=[0.5, 0.5])) rr.log("text_log", rr.TextLog(f"hello {i}")) - rr.log("scalar", rr.Scalar(math.sin(i / 100 * 2 * math.pi))) + rr.log("scalar", rr.Scalars(math.sin(i / 100 * 2 * math.pi))) depth_image = 100 * np.ones((10, 100), dtype=np.float32) depth_image[:, i] = 50 diff --git a/tests/rust/experimental_multi_scalar/Cargo.toml b/tests/rust/experimental_multi_scalar/Cargo.toml deleted file mode 100644 index 7022bc8105a1..000000000000 --- a/tests/rust/experimental_multi_scalar/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "experimental_multi_scalar" -version.workspace = true -edition.workspace = true -rust-version.workspace = true -license.workspace = true -publish = false - -[lints] -workspace = true - -[dependencies] -rerun = { path = "../../../crates/top/rerun" } - -# TODO(#9005): Remove this "test" again. This should be a proper snippet. diff --git a/tests/rust/experimental_multi_scalar/src/main.rs b/tests/rust/experimental_multi_scalar/src/main.rs deleted file mode 100644 index 7afb7910a98a..000000000000 --- a/tests/rust/experimental_multi_scalar/src/main.rs +++ /dev/null @@ -1,73 +0,0 @@ -//! Experimenting with multi-scalar logging. - -fn main() -> Result<(), Box> { - let rec = rerun::RecordingStreamBuilder::new("rerun_example_scalar").spawn()?; - - // Simple: Static color & stroke width. - - rec.log_static( - "scalar", - &rerun::SeriesLine::new() - .with_many_color([ - rerun::Color::from_rgb(255, 0, 0), - rerun::Color::from_rgb(0, 0, 255), - ]) - .with_many_width([2.0, 4.0]) - .with_many_name(["sin", "cos"]) - .with_visible_series([false, true]), - )?; - - for step in 0..64 { - rec.set_time_sequence("step", step); - rec.log( - "scalar", - &rerun::Scalar::update_fields() - .with_many_scalar([(step as f64 / 10.0).sin(), (step as f64 / 10.0).cos()]), - )?; - } - - // Complex: Color & stroke width changing over time. - - for step in 0..64 { - rec.set_time_sequence("step", step); - - rec.log( - "multi_colored", - &rerun::SeriesLine::new() - .with_many_color([ - rerun::Color::from_rgb(step * 4, 255 - step * 4, 0), - rerun::Color::from_rgb(0, step * 4, 255 - step * 4), - ]) - .with_many_width([(64.0 - step as f32) * 0.5, step as f32 * 0.5]), - )?; - - match step { - 32..40 => { - // Partial gap. - rec.log( - "multi_colored", - &rerun::Scalar::update_fields() - .with_many_scalar([(step as f64 / 10.0).sin() + 2.0]), - )?; - } - - 40 => { - // full gap - rec.log("multi_colored", &rerun::Clear::new(false))?; - } - 41..55 => {} - - _ => { - rec.log( - "multi_colored", - &rerun::Scalar::update_fields().with_many_scalar([ - (step as f64 / 10.0).sin() + 2.0, - (step as f64 / 10.0).cos() + 2.0, - ]), - )?; - } - } - } - - Ok(()) -} diff --git a/tests/rust/plot_dashboard_stress/src/main.rs b/tests/rust/plot_dashboard_stress/src/main.rs index 5b26de2c4b04..5ee2b66c1bd8 100644 --- a/tests/rust/plot_dashboard_stress/src/main.rs +++ b/tests/rust/plot_dashboard_stress/src/main.rs @@ -156,12 +156,10 @@ fn run(rec: &rerun::RecordingStream, args: &Args) -> anyhow::Result<()> { "sim_time", seconds.copied(), )], - rerun::Scalar::update_fields() - .with_many_scalar(values.copied()) - .columns_of_unit_batches()?, + rerun::Scalars::new(values.copied()).columns_of_unit_batches()?, )?; } else { - rec.log(path, &rerun::Scalar::new(series_values[offset]))?; + rec.log(path, &rerun::Scalars::one(series_values[offset]))?; } } } diff --git a/tests/rust/test_temporal_batch/src/main.rs b/tests/rust/test_temporal_batch/src/main.rs index 513f657c0897..482d85fc2947 100644 --- a/tests/rust/test_temporal_batch/src/main.rs +++ b/tests/rust/test_temporal_batch/src/main.rs @@ -11,8 +11,8 @@ fn main() -> Result<(), Box> { rec.send_columns( "scalar", [timeline_values], - rerun::Scalar::update_fields() - .with_many_scalar(scalar_data) + rerun::Scalars::update_fields() + .with_scalars(scalar_data) .columns_of_unit_batches()?, )?;