Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support mashup of both rolling and 2D graph panels #16

Merged
merged 4 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions src/Bonsai.Gui.Visualizers/BarGraphBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ internal class VisualizerController
internal string IndexLabel;
internal string[] ValueLabels;
internal CurveConfiguration[] CurveSettings;
internal Action<object, IBarGraphVisualizer> AddValues;
internal Action<DateTime, object, IBarGraphVisualizer> AddValues;
internal BarBase BaseAxis;
internal BarType BarType;
}
Expand All @@ -103,6 +103,7 @@ public override Expression Build(IEnumerable<Expression> 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(IBarGraphVisualizer));
var elementVariable = Expression.Variable(parameterType);
Expand All @@ -116,7 +117,7 @@ public override Expression Build(IEnumerable<Expression> arguments)
CurveSettings = CurveSettings.ToArray()
};

var selectedIndex = GraphHelper.SelectIndexMember(elementVariable, IndexSelector, out Controller.IndexLabel);
var selectedIndex = GraphHelper.SelectIndexMember(timeParameter, elementVariable, IndexSelector, out Controller.IndexLabel);
Controller.IndexType = selectedIndex.Type;
if (selectedIndex.Type != typeof(double) && selectedIndex.Type != typeof(string))
{
Expand All @@ -127,7 +128,11 @@ public override Expression Build(IEnumerable<Expression> arguments)
var addValuesBody = Expression.Block(new[] { elementVariable },
Expression.Assign(elementVariable, Expression.Convert(valueParameter, parameterType)),
Expression.Call(viewParameter, nameof(IBarGraphVisualizer.AddValues), null, selectedIndex, selectedValues));
Controller.AddValues = Expression.Lambda<Action<object, IBarGraphVisualizer>>(addValuesBody, valueParameter, viewParameter).Compile();
Controller.AddValues = Expression.Lambda<Action<DateTime, object, IBarGraphVisualizer>>(
addValuesBody,
timeParameter,
valueParameter,
viewParameter).Compile();
return Expression.Call(typeof(BarGraphBuilder), nameof(Process), new[] { parameterType }, source);
}

Expand Down
8 changes: 4 additions & 4 deletions src/Bonsai.Gui.Visualizers/BarGraphOverlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
using Bonsai.Expressions;
using ZedGraph;

[assembly: TypeVisualizer(typeof(BarGraphOverlay), Target = typeof(MashupSource<GraphPanelVisualizer, BarGraphVisualizer>))]
[assembly: TypeVisualizer(typeof(BarGraphOverlay), Target = typeof(MashupSource<RollingGraphPanelVisualizer, BarGraphVisualizer>))]


namespace Bonsai.Gui.Visualizers
Expand All @@ -18,7 +18,7 @@ namespace Bonsai.Gui.Visualizers
/// </summary>
public class BarGraphOverlay : BufferedVisualizer, IBarGraphVisualizer
{
GraphPanelVisualizer visualizer;
RollingGraphPanelVisualizer visualizer;
BarGraphBuilder.VisualizerController controller;
BoundedPointPairList[] series;

Expand Down Expand Up @@ -83,7 +83,7 @@ void AddBaseY()
/// <inheritdoc/>
public override void Load(IServiceProvider provider)
{
visualizer = (GraphPanelVisualizer)provider.GetService(typeof(MashupVisualizer));
visualizer = (RollingGraphPanelVisualizer)provider.GetService(typeof(MashupVisualizer));
var context = (ITypeVisualizerContext)provider.GetService(typeof(ITypeVisualizerContext));
var barGraphBuilder = (BarGraphBuilder)ExpressionBuilder.GetVisualizerElement(context.Source).Builder;
controller = barGraphBuilder.Controller;
Expand Down Expand Up @@ -141,7 +141,7 @@ public override void Show(object value)
/// <inheritdoc/>
protected override void Show(DateTime time, object value)
{
controller.AddValues(value, this);
controller.AddValues(time, value, this);
}

/// <inheritdoc/>
Expand Down
18 changes: 12 additions & 6 deletions src/Bonsai.Gui.Visualizers/BarGraphVisualizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,6 @@ public override void Load(IServiceProvider provider)
}
}

/// <inheritdoc/>
public override void Show(object value)
{
controller.AddValues(value, this);
}

/// <inheritdoc/>
protected override void ShowBuffer(IList<Timestamped<object>> values)
{
Expand All @@ -164,6 +158,18 @@ protected override void ShowBuffer(IList<Timestamped<object>> values)
}
}

/// <inheritdoc/>
public override void Show(object value)
{
Show(DateTime.Now, value);
}

/// <inheritdoc/>
protected override void Show(DateTime time, object value)
{
controller.AddValues(time, value, this);
}

/// <inheritdoc/>
public override void SequenceCompleted()
{
Expand Down
8 changes: 4 additions & 4 deletions src/Bonsai.Gui.Visualizers/Bonsai.Gui.Visualizers.csproj.user
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@
<Compile Update="GraphControl.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Update="GraphPanel.cs">
<Compile Update="RollingGraphPanel.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Update="GraphPanel2D.cs">
<Compile Update="GraphPanel.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Update="GraphPanelView.cs">
<Compile Update="RollingGraphPanelView.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Update="GraphPanelView2D.cs">
<Compile Update="GraphPanelView.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Update="LineGraph.cs">
Expand Down
2 changes: 1 addition & 1 deletion src/Bonsai.Gui.Visualizers/GraphHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
75 changes: 53 additions & 22 deletions src/Bonsai.Gui.Visualizers/GraphPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,56 +4,87 @@ namespace Bonsai.Gui.Visualizers
{
internal class GraphPanel : BoundedGraphPanel
{
bool autoScale;
bool autoScaleX;
bool autoScaleY;

public GraphPanel()
{
autoScale = true;
autoScaleX = true;
autoScaleY = true;
}

public Axis ScaleAxis => GraphPane.BarSettings.Base switch
public double XMin
{
BarBase.Y => GraphPane.XAxis,
BarBase.Y2 => GraphPane.X2Axis,
BarBase.X2 => GraphPane.Y2Axis,
_ => GraphPane.YAxis
};
get { return GraphPane.XAxis.Scale.Min; }
set
{
GraphPane.XAxis.Scale.Min = value;
GraphPane.AxisChange();
Invalidate();
}
}

public double Min
public double XMax
{
get { return ScaleAxis.Scale.Min; }
get { return GraphPane.XAxis.Scale.Max; }
set
{
ScaleAxis.Scale.Min = value;
GraphPane.XAxis.Scale.Max = value;
GraphPane.AxisChange();
Invalidate();
}
}

public double Max
public double YMin
{
get { return ScaleAxis.Scale.Max; }
get { return GraphPane.YAxis.Scale.Min; }
set
{
ScaleAxis.Scale.Max = value;
GraphPane.YAxis.Scale.Min = value;
GraphPane.AxisChange();
Invalidate();
}
}

public bool AutoScale
public double YMax
{
get { return GraphPane.YAxis.Scale.Max; }
set
{
GraphPane.YAxis.Scale.Max = value;
GraphPane.AxisChange();
Invalidate();
}
}

public bool AutoScaleX
{
get { return autoScaleX; }
set
{
var changed = autoScaleX != value;
autoScaleX = value;
if (changed)
{
GraphPane.XAxis.Scale.MaxAuto = autoScaleX;
GraphPane.XAxis.Scale.MinAuto = autoScaleX;
if (autoScaleX) Invalidate();
}
}
}

public bool AutoScaleY
{
get { return autoScale; }
get { return autoScaleY; }
set
{
var changed = autoScale != value;
autoScale = value;
var changed = autoScaleY != value;
autoScaleY = value;
if (changed)
{
var baseAxis = ScaleAxis;
baseAxis.Scale.MaxAuto = autoScale;
baseAxis.Scale.MinAuto = autoScale;
if (autoScale) Invalidate();
GraphPane.YAxis.Scale.MaxAuto = autoScaleY;
GraphPane.YAxis.Scale.MinAuto = autoScaleY;
if (autoScaleY) Invalidate();
}
}
}
Expand Down
84 changes: 23 additions & 61 deletions src/Bonsai.Gui.Visualizers/GraphPanelBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
using System.Linq.Expressions;
using System.Reactive.Linq;
using System.Reactive;
using Bonsai.Expressions;
using ZedGraph;

namespace Bonsai.Gui.Visualizers
{
Expand All @@ -14,86 +12,50 @@ namespace Bonsai.Gui.Visualizers
/// </summary>
[TypeVisualizer(typeof(GraphPanelVisualizer))]
[Description("Specifies a mashup graph panel that can be used to combine multiple plots sharing the same axes.")]
public class GraphPanelBuilder : ZeroArgumentExpressionBuilder, INamedElement
public class GraphPanelBuilder : GraphPanelBuilderBase
{
/// <summary>
/// Gets or sets the name of the visualizer window.
/// </summary>
[Category(nameof(CategoryAttribute.Design))]
[Description("The name of the visualizer window.")]
public string Name { get; set; }

/// <summary>
/// Gets or sets a value specifying the axis on which the bars in the graph will be displayed.
/// </summary>
[TypeConverter(typeof(BaseAxisConverter))]
[Category(nameof(CategoryAttribute.Appearance))]
[Description("Specifies the axis on which the bars in the graph will be displayed.")]
public BarBase BaseAxis { get; set; }

/// <summary>
/// Gets or sets a value specifying how the different bars in the graph will be visually arranged.
/// </summary>
[Category(nameof(CategoryAttribute.Appearance))]
[Description("Specifies how the different bars in the graph will be visually arranged.")]
public BarType BarType { get; set; }

/// <summary>
/// Gets or sets a value specifying whether the scale values are reversed on the X-axis.
/// </summary>
[Category(nameof(CategoryAttribute.Appearance))]
[Description("Specifies whether the scale values are reversed on the X-axis.")]
public bool ReverseX { get; set; }

/// <summary>
/// Gets or sets a value specifying whether the scale values are reversed on the Y-axis.
/// </summary>
[Category(nameof(CategoryAttribute.Appearance))]
[Description("Specifies whether the scale values are reversed on the Y-axis.")]
public bool ReverseY { get; set; }

/// <summary>
/// Gets or sets the optional maximum span of data displayed at any one moment in the graph.
/// If no span is specified, all data points will be displayed.
/// Gets or sets a value specifying a fixed lower limit for the X-axis range.
/// If no fixed range is specified, the graph limits can be edited online.
/// </summary>
[Category("Range")]
[Description("The optional maximum span of data displayed at any one moment in the graph. " +
"If no span is specified, all data points will be displayed.")]
public double? Span { get; set; }
[Description("Specifies the optional fixed lower limit of the X-axis range.")]
public double? XMin { get; set; }

/// <summary>
/// Gets or sets the optional capacity used for rolling line graphs. If no capacity is specified, all data points will be displayed.
/// Gets or sets a value specifying a fixed upper limit for the X-axis range.
/// If no fixed range is specified, the graph limits can be edited online.
/// </summary>
[Category("Range")]
[Description("The optional capacity used for rolling line graphs. If no capacity is specified, all data points will be displayed.")]
public int? Capacity { get; set; }
[Description("Specifies the optional fixed upper limit of the X-axis range.")]
public double? XMax { get; set; }

/// <summary>
/// Gets or sets a value specifying a fixed lower limit for the axis range.
/// Gets or sets a value specifying a fixed lower limit for the Y-axis range.
/// If no fixed range is specified, the graph limits can be edited online.
/// </summary>
[Category("Range")]
[Description("Specifies the optional fixed lower limit of the axis range.")]
public double? Min { get; set; }
[Description("Specifies the optional fixed lower limit of the Y-axis range.")]
public double? YMin { get; set; }

/// <summary>
/// Gets or sets a value specifying a fixed upper limit for the axis range.
/// Gets or sets a value specifying a fixed upper limit for the Y-axis range.
/// If no fixed range is specified, the graph limits can be edited online.
/// </summary>
[Category("Range")]
[Description("Specifies the optional fixed upper limit of the axis range.")]
public double? Max { get; set; }
[Description("Specifies the optional fixed upper limit of the Y-axis range.")]
public double? YMax { get; set; }

internal VisualizerController Controller { get; set; }

internal class VisualizerController
{
internal BarBase BaseAxis;
internal BarType BarType;
internal double? Span;
internal int? Capacity;
internal double? Min;
internal double? Max;
internal double? XMin;
internal double? XMax;
internal double? YMin;
internal double? YMax;
internal bool ReverseX;
internal bool ReverseY;
}
Expand All @@ -107,12 +69,12 @@ public override Expression Build(IEnumerable<Expression> arguments)
{
Controller = new VisualizerController
{
BaseAxis = BaseAxis,
BarType = BarType,
Span = Span,
Capacity = Capacity,
Min = Min,
Max = Max,
XMin = XMin,
XMax = XMax,
YMin = YMin,
YMax = YMax,
ReverseX = ReverseX,
ReverseY = ReverseY
};
Expand Down
Loading
Loading