A simple panel to graphically show the Connections in the Bench Settings.
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Keysight.OpenTap.Wpf;
using OpenTap;
using OxyPlot;
using OxyPlot.Axes;
using OxyPlot.Legends;
using OxyPlot.Series;
using OxyPlot.Wpf;
using HorizontalAlignment = System.Windows.HorizontalAlignment;
using VerticalAlignment = System.Windows.VerticalAlignment;
namespace TTap.Plugins.Core.Common
{
    [Display("Connections Path Loss")]
    public class DockPanelConnections : ITapDockPanel
    {
        static TraceSource _log = Log.CreateSource("ConnectionsPanel");
        private PlotModel _plotModel;
        public FrameworkElement CreateElement(ITapDockContext context)
        {
            _log.Info($"Creating Connections chart...");
            var loadPlanBtn = new Button() { Content = "Update Chart" };
            var panel = new Grid();
            panel.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); // For the button
            panel.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) }); // For the PlotView
            Grid.SetRow(loadPlanBtn, 0); // Place the button in the first row
            panel.Children.Add(loadPlanBtn);
            loadPlanBtn.Click += (s, e) =>
            {
                _log.Info($"Updating Connections chart...");
                _plotModel = CreatePlotModel(_plotModel);
                _plotModel.InvalidatePlot(true);
            };
            _plotModel = new PlotModel { Title = "Connection Path Loss", IsLegendVisible = true };
            CreatePlotModel(_plotModel);
            var plotView = new PlotView
            {
                Model = _plotModel,
                HorizontalAlignment = HorizontalAlignment.Stretch,
                VerticalAlignment = VerticalAlignment.Stretch,
            };
            // Add the PlotView to your WPF Grid
            Grid.SetRow(plotView, 1);
            panel.Children.Add(plotView);
            // Refresh the plot
            _plotModel.InvalidatePlot(true);
            //// Move the tracker to the top left-hand corner, but it also removes the cross-hairs
            //// Create a new ControlTemplate
            //var template = new ControlTemplate();
            //// Create a FrameworkElementFactory that creates a TextBlock
            //var textBlockFactory = new FrameworkElementFactory(typeof(TextBlock));
            //// Set the TextBlock's Text binding and Foreground color
            //textBlockFactory.SetBinding(TextBlock.TextProperty, new Binding());
            //textBlockFactory.SetValue(TextBlock.ForegroundProperty, Brushes.Black);
            //// Set the ControlTemplate's VisualTree to the created TextBlock
            //template.VisualTree = textBlockFactory;
            //// Set the PlotView's DefaultTrackerTemplate to the created ControlTemplate
            //plotView.DefaultTrackerTemplate = template;
            // Changes the tracker text to red.
            // Create a new Style for TrackerControl
            var style = new Style(typeof(TrackerControl));
            // Create a Setter for the Foreground property
            var setter = new Setter(TrackerControl.ForegroundProperty, Brushes.Red);
            // Add the Setter to the Style
            style.Setters.Add(setter);
            // Add the Style to the application's resources
            Application.Current.Resources.Add(typeof(TrackerControl), style);
            return panel;
        }
        public double? DesiredWidth => 200;
        public double? DesiredHeight => 200;
        private static PlotModel CreatePlotModel(PlotModel plotModel)
        {
            //var freqMin = ComponentSettings<ConnectionSettings>.Current.OfType<RfConnection>().Select(x => x.CableLoss.Min(cl => cl.Frequency)).Min();
            //var freqMax = ComponentSettings<ConnectionSettings>.Current.OfType<RfConnection>().Select(x => x.CableLoss.Max(cl => cl.Frequency)).Max();
            var xAxis = new LinearAxis
            {
                Position = AxisPosition.Bottom,
                Title = "Frequency (MHz)",
                LabelFormatter = value => $"{value / 1e6} MHz"
            };
            // Set up the Y axis
            var yAxis = new LinearAxis
            {
                Position = AxisPosition.Left,
                Title = "Loss (dB)",
            };
            if (plotModel.Axes.Any())
                plotModel.Axes.Clear();
            plotModel.Axes.Add(xAxis);
            plotModel.Axes.Add(yAxis);
            if (plotModel.Series.Any())
                plotModel.Series.Clear();
            foreach (var con in ComponentSettings<ConnectionSettings>.Current)
            {
                if (!(con is RfConnection rfCon)) continue;
                _log.Info($"Plotting {con.Name}");
                // Set up the series
                var series = new LineSeries { Title = rfCon.Name, TrackerFormatString = "{0}\n{1}: {2:###0,,.000}\n{3}: {4:F2}" };
                plotModel.Series.Add(series);
                foreach (var point in rfCon.CableLoss)
                {
                    series.Points.Add(new DataPoint(point.Frequency, point.Loss));
                }
            }
            if (plotModel.Legends.Any())
                plotModel.Legends.Clear();
            plotModel.Legends.Add(new Legend() { LegendPosition = LegendPosition.RightTop, LegendPlacement = LegendPlacement.Outside });
            return plotModel;
        }
    }
}

