From edc20b757f6e5c386c31341d6206240af035ba71 Mon Sep 17 00:00:00 2001 From: glopesdev Date: Mon, 25 Mar 2024 17:27:55 +0000 Subject: [PATCH] Add index and curve settings to line graphs --- src/Bonsai.Gui.Visualizers/GraphHelper.cs | 2 +- .../LineGraphBuilder.cs | 46 +++++++++++++++++-- .../LineGraphVisualizer.cs | 24 ++++++---- src/Bonsai.Gui.Visualizers/RollingGraph.cs | 4 +- 4 files changed, 59 insertions(+), 17 deletions(-) diff --git a/src/Bonsai.Gui.Visualizers/GraphHelper.cs b/src/Bonsai.Gui.Visualizers/GraphHelper.cs index 085b65b..bdbc782 100644 --- a/src/Bonsai.Gui.Visualizers/GraphHelper.cs +++ b/src/Bonsai.Gui.Visualizers/GraphHelper.cs @@ -150,7 +150,7 @@ internal static Expression SelectDataPoints(Expression expression, string valueS if (memberNames.Length == 1) { var memberName = memberNames[0]; - valueLabels = memberName != ExpressionHelper.ImplicitParameterName ? new[] { memberName } : null; + valueLabels = new[] { memberName }; var member = ExpressionHelper.MemberAccess(expression, memberNames[0]); if (member.Type.IsArray) { diff --git a/src/Bonsai.Gui.Visualizers/LineGraphBuilder.cs b/src/Bonsai.Gui.Visualizers/LineGraphBuilder.cs index 44613a7..cabedf6 100644 --- a/src/Bonsai.Gui.Visualizers/LineGraphBuilder.cs +++ b/src/Bonsai.Gui.Visualizers/LineGraphBuilder.cs @@ -1,6 +1,7 @@ using Bonsai.Expressions; using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Linq.Expressions; @@ -17,6 +18,13 @@ namespace Bonsai.Gui.Visualizers [Description("A visualizer that plots each element of the sequence as a line graph.")] public class LineGraphBuilder : SingleArgumentExpressionBuilder { + /// + /// Gets or sets the name of the property that will be used as index for the graph. + /// + [Editor("Bonsai.Design.MemberSelectorEditor, Bonsai.Design", DesignTypes.UITypeEditor)] + [Description("The name of the property that will be used as index for the graph.")] + public string IndexSelector { get; set; } + /// /// Gets or sets the names of the properties to be displayed in the graph. /// Each selected property must have a point pair compatible type. @@ -39,6 +47,13 @@ public class LineGraphBuilder : SingleArgumentExpressionBuilder [Description("The width, in points, to be used for the line graph. Use a value of zero to hide the line.")] public float LineWidth { get; set; } = 1; + /// + /// Gets the optional settings for each line added to the graph. + /// + [Category(nameof(CategoryAttribute.Appearance))] + [Description("Specifies optional settings for each line added to the graph.")] + public Collection CurveSettings { get; } = new(); + /// /// Gets or sets the optional capacity used for rolling line graphs. If no capacity is specified, all data points will be displayed. /// @@ -87,11 +102,14 @@ internal class VisualizerController internal double? XMax; internal double? YMin; internal double? YMax; + internal Type IndexType; + internal string IndexLabel; internal bool LabelAxes; internal string[] ValueLabels; internal SymbolType SymbolType; internal float LineWidth; - internal Action AddValues; + internal CurveConfiguration[] CurveSettings; + internal Action AddValues; } /// @@ -103,8 +121,9 @@ public override Expression Build(IEnumerable arguments) { var source = arguments.First(); var parameterType = source.Type.GetGenericArguments()[0]; + var timeParameter = Expression.Parameter(typeof(DateTime)); var valueParameter = Expression.Parameter(typeof(object)); - var viewParameter = Expression.Parameter(typeof(LineGraphVisualizer)); + var viewParameter = Expression.Parameter(typeof(ILineGraphVisualizer)); var elementVariable = Expression.Variable(parameterType); Controller = new VisualizerController { @@ -114,9 +133,17 @@ public override Expression Build(IEnumerable arguments) YMin = YMin, YMax = YMax, SymbolType = SymbolType, - LineWidth = LineWidth + LineWidth = LineWidth, + CurveSettings = CurveSettings.ToArray() }; + var selectedIndex = GraphHelper.SelectIndexMember(timeParameter, elementVariable, IndexSelector, out Controller.IndexLabel); + Controller.IndexType = selectedIndex.Type; + if (selectedIndex.Type != typeof(double) && selectedIndex.Type != typeof(string)) + { + selectedIndex = Expression.Convert(selectedIndex, typeof(double)); + } + var selectedValues = GraphHelper.SelectDataPoints( elementVariable, ValueSelector, @@ -124,8 +151,12 @@ public override Expression Build(IEnumerable arguments) out Controller.LabelAxes); var addValuesBody = Expression.Block(new[] { elementVariable }, Expression.Assign(elementVariable, Expression.Convert(valueParameter, parameterType)), - Expression.Call(viewParameter, nameof(LineGraphVisualizer.AddValues), null, selectedValues)); - Controller.AddValues = Expression.Lambda>(addValuesBody, valueParameter, viewParameter).Compile(); + Expression.Call(viewParameter, nameof(ILineGraphVisualizer.AddValues), null, selectedIndex, selectedValues)); + Controller.AddValues = Expression.Lambda>( + addValuesBody, + timeParameter, + valueParameter, + viewParameter).Compile(); return Expression.Call(typeof(LineGraphBuilder), nameof(Process), new[] { parameterType }, source); } @@ -134,4 +165,9 @@ static IObservable Process(IObservable source) return source; } } + + interface ILineGraphVisualizer + { + void AddValues(double index, params PointPair[] values); + } } diff --git a/src/Bonsai.Gui.Visualizers/LineGraphVisualizer.cs b/src/Bonsai.Gui.Visualizers/LineGraphVisualizer.cs index 861a54d..a980210 100644 --- a/src/Bonsai.Gui.Visualizers/LineGraphVisualizer.cs +++ b/src/Bonsai.Gui.Visualizers/LineGraphVisualizer.cs @@ -11,7 +11,7 @@ namespace Bonsai.Gui.Visualizers /// /// Provides a type visualizer to display an object as a line graph. /// - public class LineGraphVisualizer : BufferedVisualizer + public class LineGraphVisualizer : BufferedVisualizer, ILineGraphVisualizer { LineGraphBuilder.VisualizerController controller; LineGraphView view; @@ -55,7 +55,7 @@ public class LineGraphVisualizer : BufferedVisualizer /// public bool AutoScaleY { get; set; } = true; - internal void AddValues(PointPair[] values) + void ILineGraphVisualizer.AddValues(double index, params PointPair[] values) { if (view.Graph.NumSeries != values.Length || reset) { @@ -65,7 +65,7 @@ internal void AddValues(PointPair[] values) reset); reset = false; } - view.Graph.AddValues(values); + view.Graph.AddValues(index, values); } /// @@ -157,12 +157,6 @@ public override void Load(IServiceProvider provider) } } - /// - public override void Show(object value) - { - controller.AddValues(value, this); - } - /// protected override void ShowBuffer(IList> values) { @@ -173,6 +167,18 @@ protected override void ShowBuffer(IList> values) } } + /// + public override void Show(object value) + { + Show(DateTime.Now, value); + } + + /// + protected override void Show(DateTime time, object value) + { + controller.AddValues(time, value, this); + } + /// public override void SequenceCompleted() { diff --git a/src/Bonsai.Gui.Visualizers/RollingGraph.cs b/src/Bonsai.Gui.Visualizers/RollingGraph.cs index 09545df..6d8ed49 100644 --- a/src/Bonsai.Gui.Visualizers/RollingGraph.cs +++ b/src/Bonsai.Gui.Visualizers/RollingGraph.cs @@ -176,11 +176,11 @@ public void AddValues(double index, string label, params double[] values) } } - public void AddValues(params PointPair[] values) + public void AddValues(double index, params PointPair[] values) { for (int i = 0; i < series.Length; i++) { - series[i].Add(values[i]); + series[i].Add(values[i].X, values[i].Y, index, values[i].Tag); } }