This commit is contained in:
2026-04-17 14:55:32 -04:00
commit bc3ac1d4c9
18017 changed files with 4371742 additions and 0 deletions

View File

@@ -0,0 +1 @@
12

View File

@@ -0,0 +1 @@
12

View File

@@ -0,0 +1,306 @@
<base:BaseView x:Class="DTS.Viewer.Graph.TestDataSeriesView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:base="clr-namespace:DTS.Common.Base;assembly=DTS.Common"
xmlns:c1="http://schemas.componentone.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:converters="clr-namespace:DTS.Common.Converters;assembly=DTS.Common"
mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="800"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" x:Name="testDataSeriesView">
<base:BaseView.Resources>
<ResourceDictionary >
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Resources/CommonStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style TargetType="TextBlock" x:Key="OverlayStyle">
<Setter Property="FontSize" Value="12"/>
<Setter Property="Foreground" Value="#D0000000"/>
</Style>
<converters:BooleanToVisibilityConverter x:Key="BoolToVisConverter" />
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBoolToVisConverter" />
</ResourceDictionary>
</base:BaseView.Resources>
<Grid x:Name="GraphViewGrid" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<c1:C1Chart x:Name="MainChart" Style="{DynamicResource LineChartStyle}" Margin="0"
MouseWheel="MainChart_OnMouseWheel" IsManipulationEnabled="True" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="ActionLeave">
<i:InvokeCommandAction Command="{Binding ActionLeaveCommand}" CommandParameter="{Binding ElementName=MainChart}"/>
</i:EventTrigger>
<i:EventTrigger EventName="ActionEnter">
<i:InvokeCommandAction Command="{Binding ActionEnterCommand}" CommandParameter="{Binding ElementName=MainChart}"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseUp">
<i:InvokeCommandAction Command="{Binding MouseUpCommand}" CommandParameter="{Binding ElementName=MainChart}"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseDown">
<i:InvokeCommandAction Command="{Binding MouseDownCommand}" CommandParameter="{Binding ElementName=MainChart}"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseMove">
<i:InvokeCommandAction Command="{Binding MouseMoveCommand}" CommandParameter="{Binding ElementName=MainChart}"/>
</i:EventTrigger>
<i:EventTrigger EventName="GotFocus">
<i:InvokeCommandAction Command="{Binding GotFocusCommand}" CommandParameter="{Binding ElementName=MainChart}"/>
</i:EventTrigger>
<i:EventTrigger EventName="KeyUp">
<i:InvokeCommandAction Command="{Binding ChartOnKeyUpCommand}" />
</i:EventTrigger>
<!--<i:EventTrigger EventName="KeyUp">
<ei:CallMethodAction MethodName="{Binding ChartOnKeyUpMethod}" TargetObject="{Binding}"/>
</i:EventTrigger>-->
</i:Interaction.Triggers>
<c1:LineAreaOptions.OptimizationRadius>5</c1:LineAreaOptions.OptimizationRadius>
<c1:C1Chart.Actions>
<c1:ZoomAction Fill="{StaticResource Brush_ChartZoomBackground}" Stroke="{x:Null}" Block.IsHyphenationEnabled="False"/>
<c1:TranslateAction Modifiers="Shift" />
<c1:ScaleAction Modifiers="Control" />
</c1:C1Chart.Actions>
<c1:C1Chart.View >
<c1:ChartView Focusable="True">
<c1:ChartView.AxisX>
<c1:Axis Style="{DynamicResource LineChartAxisStyle}" MajorGridStroke="#30000000" MajorGridStrokeThickness="1">
<c1:Axis.ScrollBar>
<c1:AxisScrollBar Margin="0,10,0,0" />
</c1:Axis.ScrollBar>
</c1:Axis>
</c1:ChartView.AxisX>
<c1:ChartView.AxisY>
<c1:Axis Style="{DynamicResource LineChartAxisStyle}" MajorGridStroke="#30000000" MajorGridStrokeThickness="1">
<c1:Axis.ScrollBar>
<c1:AxisScrollBar Margin="0,10,0,0"/>
</c1:Axis.ScrollBar>
</c1:Axis>
</c1:ChartView.AxisY>
<!-- Markers layer -->
<c1:ChartView.Layers>
<c1:ChartPanel Visibility="{Binding Path=MarkerVisibilty}" >
<!-- vertical line and dot markers -->
<c1:ChartPanelObject x:Name="Label"
Attach="DataX"
Action="MouseMove"
DataPoint="0,0"
HorizontalAlignment="Left"
VerticalAlignment="Bottom" RenderTransformOrigin="0.5,0.5">
<c1:ChartPanelObject.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform X="5"/>
<TranslateTransform Y="-5"/>
</TransformGroup>
</c1:ChartPanelObject.RenderTransform>
<Grid DataContext="{Binding RelativeSource={x:Static RelativeSource.Self},Path=Parent}">
<Rectangle Fill="Transparent" Opacity=".95" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
<StackPanel Margin="5,2" Orientation="Horizontal">
<!-- ReSharper disable once Xaml.BindingWithContextNotResolved -->
<TextBlock x:Name="LabelY" Text="{Binding DataPoint.Y, StringFormat=F3}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Text=" @ " VerticalAlignment="Center" HorizontalAlignment="Center"/>
<!-- ReSharper disable once Xaml.BindingWithContextNotResolved -->
<TextBlock x:Name="LabelX" Text="{Binding DataPoint.X, StringFormat=F3}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock x:Name="LabelTimeUnits" Text="ms" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</StackPanel>
</Grid>
</c1:ChartPanelObject>
<c1:ChartPanelObject x:Name="Dot"
Attach="DataX"
Action="MouseMove"
DataPoint="0,0"
DataPointChanged="obj_DataPointChanged"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Ellipse Fill="#55FFFFFF" Stroke="Black" StrokeThickness=".5" Width="10" Height="10" />
</c1:ChartPanelObject>
</c1:ChartPanel>
</c1:ChartView.Layers>
</c1:ChartView>
</c1:C1Chart.View>
<c1:C1ChartLegend Grid.Row="1" x:Name="Legend" Visibility="Collapsed" Foreground="{DynamicResource Brush_ChartForeground}"/>
</c1:C1Chart>
<Grid HorizontalAlignment="Right" Background="#D0FFFFFF" VerticalAlignment="Top"
Margin="10" Visibility="{Binding OverlayVisibility}"
Width="300">
<Grid.Style>
<Style TargetType="Grid">
<Style.Triggers>
<EventTrigger RoutedEvent="Control.MouseEnter">
<BeginStoryboard>
<Storyboard >
<DoubleAnimation Duration="0:0:0.2" To="0" Storyboard.TargetProperty="Opacity"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Control.MouseLeave">
<BeginStoryboard>
<Storyboard >
<DoubleAnimation Duration="0:0:0.2" To="1" Storyboard.TargetProperty="Opacity"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Test Setup: " Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding TestSetupName}" Style="{StaticResource OverlayStyle}" TextWrapping="Wrap"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Test Id: " Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding TestId}" Style="{StaticResource OverlayStyle}" TextWrapping="Wrap"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="Group Name: " Style="{StaticResource OverlayStyle}" Visibility="Collapsed"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding GroupName}" Style="{StaticResource OverlayStyle}" Visibility="Collapsed"/>
<TextBlock Grid.Row="3" Grid.Column="0" Text="Hardware Channel: " Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="3" Grid.Column="1" Text="{Binding HardwareChannel}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="4" Grid.Column="0" Text="Serial Number: " Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="4" Grid.Column="1" Text="{Binding SensorSN}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="5" Grid.Column="0" Text="Channel Description: " Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="5" Grid.Column="1" Text="{Binding Description}" Style="{StaticResource OverlayStyle}" TextWrapping="Wrap"/>
<TextBlock Grid.Row="6" Grid.Column="0" Text="Channel User Code: " Style="{StaticResource OverlayStyle}" Visibility="{Binding UserVisibility}"/>
<TextBlock Grid.Row="6" Grid.Column="1" Text="{Binding UserCode}" Style="{StaticResource OverlayStyle}" TextWrapping="Wrap" Visibility="{Binding UserVisibility}"/>
<TextBlock Grid.Row="7" Grid.Column="0" Text="Channel User Name: " Style="{StaticResource OverlayStyle}" Visibility="{Binding UserVisibility}"/>
<TextBlock Grid.Row="7" Grid.Column="1" Text="{Binding UserChannelName}" Style="{StaticResource OverlayStyle}" TextWrapping="Wrap" Visibility="{Binding UserVisibility}"/>
<TextBlock Grid.Row="8" Grid.Column="0" Text="Channel ISO Code: " Style="{StaticResource OverlayStyle}" Visibility="{Binding ISOVisibility}"/>
<TextBlock Grid.Row="8" Grid.Column="1" Text="{Binding ISOCode}" Style="{StaticResource OverlayStyle}" TextWrapping="Wrap" Visibility="{Binding ISOVisibility}"/>
<TextBlock Grid.Row="9" Grid.Column="0" Text="Channel ISO Name: " Style="{StaticResource OverlayStyle}" Visibility="{Binding ISOVisibility}"/>
<TextBlock Grid.Row="9" Grid.Column="1" Text="{Binding ISOChannelName}" Style="{StaticResource OverlayStyle}" TextWrapping="Wrap" Visibility="{Binding ISOVisibility}"/>
<TextBlock Grid.Row="10" Grid.Column="0" Text="Channel Name: " Style="{StaticResource OverlayStyle}" Visibility="{Binding ChannelNameOnlyVisibility}"/>
<TextBlock Grid.Row="10" Grid.Column="1" Text="{Binding UserChannelName}" Style="{StaticResource OverlayStyle}" TextWrapping="Wrap" Visibility="{Binding ChannelNameOnlyVisibility}"/>
<TextBlock Grid.Row="11" Grid.Column="0" Text="Recording Mode: " Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="11" Grid.Column="1" Text="{Binding RecordingMode}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="12" Grid.Column="0" Text="Sample Rate (Hz): " Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="12" Grid.Column="1" Text="{Binding SampleRate}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="13" Grid.Column="0" Text="Hardware Filter (Hz): " Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="13" Grid.Column="1" Text="{Binding HWAAF}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="14" Grid.Column="0" Text="Software Filter Class: " Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="14" Grid.Column="1" Text="{Binding SWAAF}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="15" Grid.Column="0" Text="Excitation (V): " Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="15" Grid.Column="1" Text="{Binding Excitation}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="16" Grid.Column="0" Text="Polarity: " Style="{StaticResource OverlayStyle}" Visibility="{Binding PolarityVisibility}"/>
<TextBlock Grid.Row="16" Grid.Column="1" Text="{Binding Polarity}" Style="{StaticResource OverlayStyle}" Visibility="{Binding PolarityVisibility}"/>
<Rectangle Grid.Row="17" Grid.ColumnSpan="2" Fill="#60000000" StrokeDashArray="" Height="1" Margin="5"/>
<StackPanel Grid.Row="18" Grid.Column="0" Orientation="Horizontal">
<TextBlock Text="Min/Max (" Style="{StaticResource OverlayStyle}"/>
<TextBlock Text="{Binding TitleY}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Text=") :" Style="{StaticResource OverlayStyle}"/>
</StackPanel>
<StackPanel Grid.Row="18" Grid.Column="1" Orientation="Horizontal">
<TextBlock Text="{Binding MinY}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Text="/" Style="{StaticResource OverlayStyle}"/>
<TextBlock Text="{Binding MaxY}" Style="{StaticResource OverlayStyle}"/>
</StackPanel>
<StackPanel Grid.Row="19" Grid.Column="0" Orientation="Horizontal">
<TextBlock Text="Average (" Style="{StaticResource OverlayStyle}"/>
<TextBlock Text="{Binding TitleY}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Text=") :" Style="{StaticResource OverlayStyle}"/>
</StackPanel>
<TextBlock Grid.Row="19" Grid.Column="1" Text="{Binding AvgY}" Style="{StaticResource OverlayStyle}"/>
<StackPanel Grid.Row="20" Grid.Column="0" Orientation="Horizontal">
<TextBlock Text="StdDev (" Style="{StaticResource OverlayStyle}"/>
<TextBlock Text="{Binding TitleY}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Text=") :" Style="{StaticResource OverlayStyle}"/>
</StackPanel>
<TextBlock Grid.Row="20" Grid.Column="1" Text="{Binding StdDevY}" Style="{StaticResource OverlayStyle}"/>
<!-- T0 Value -->
<StackPanel Grid.Row="21" Grid.Column="0" Orientation="Horizontal" Visibility="{Binding FFT, Converter={StaticResource InverseBoolToVisConverter}}">
<TextBlock Text="Value @ T0 (" Style="{StaticResource OverlayStyle}"/>
<TextBlock Text="{Binding TitleY}" Style="{StaticResource OverlayStyle}" />
<TextBlock Text=") :" Style="{StaticResource OverlayStyle}" />
</StackPanel>
<TextBlock Grid.Row="21" Grid.Column="1" Text="{Binding T0EUValue}" Style="{StaticResource OverlayStyle}"
Visibility="{Binding FFT, Converter={StaticResource InverseBoolToVisConverter}}" />
<!-- Peek Frequency -->
<StackPanel Grid.Row="21" Grid.Column="0" Orientation="Horizontal" Visibility="{Binding FFT, Converter={StaticResource BoolToVisConverter}}">
<TextBlock Text="Peak Magnitude " Style="{StaticResource OverlayStyle}"/>
<TextBlock Text="{Binding PeakMagnitude,StringFormat=N2}" Style="{StaticResource OverlayStyle}" />
<TextBlock Text=" (dB) @ " />
</StackPanel>
<StackPanel Grid.Row="21" Grid.Column="1" Orientation="Horizontal" Visibility="{Binding FFT, Converter={StaticResource BoolToVisConverter}}">
<TextBlock Text="{Binding PeakFrequency,StringFormat=N2}" Style="{StaticResource OverlayStyle}" />
<TextBlock Text=" (Hz)" />
</StackPanel>
<!-- HIC Value -->
<StackPanel Grid.Row="22" Grid.Column="0" Orientation="Horizontal" Visibility="{Binding HIC, Converter={StaticResource BoolToVisConverter}}">
<TextBlock Text="HIC :" Style="{StaticResource OverlayStyle}" />
</StackPanel>
<TextBlock Grid.Row="22" Grid.Column="1" Text="{Binding HICValue}" Style="{StaticResource OverlayStyle}" Visibility="{Binding HIC, Converter={StaticResource BoolToVisConverter}}" />
<!-- T1 Value -->
<StackPanel Grid.Row="23" Grid.Column="0" Orientation="Horizontal" Visibility="{Binding HIC, Converter={StaticResource BoolToVisConverter}}">
<TextBlock Text="T1 (ms) :" Style="{StaticResource OverlayStyle}"/>
</StackPanel>
<TextBlock Grid.Row="23" Grid.Column="1" Text="{Binding T1Time}" Style="{StaticResource OverlayStyle}" Visibility="{Binding HIC, Converter={StaticResource BoolToVisConverter}}"/>
<!-- T2 Value -->
<StackPanel Grid.Row="24" Grid.Column="0" Orientation="Horizontal" Visibility="{Binding HIC, Converter={StaticResource BoolToVisConverter}}">
<TextBlock Text="T2 (ms) :" Style="{StaticResource OverlayStyle}"/>
</StackPanel>
<TextBlock Grid.Row="24" Grid.Column="1" Text="{Binding T2Time}" Style="{StaticResource OverlayStyle}" Visibility="{Binding HIC, Converter={StaticResource BoolToVisConverter}}"/>
</Grid>
</Grid>
</base:BaseView>

View File

@@ -0,0 +1,90 @@
using System;
using System.Windows;
using System.Windows.Input;
using C1.WPF.Chart;
using DTS.Common.Interface;
// ReSharper disable CheckNamespace
namespace DTS.Viewer.Graph
{
/// <summary>
/// Interaction logic for TestDataSeriesView.xaml
/// </summary>
public partial class TestDataView : ITestDataView
{
//bool zooming = false;
//Point ptStart = new Point();
public TestDataView()
{
InitializeComponent();
//Loaded += TestDataView_Loaded;
}
//private void TestDataView_Loaded(object sender, RoutedEventArgs e)
//{
// SetupChart();
//}
//void SetupChart()
//{
// MainChart.AddHandler(C1FlexChart.MouseLeftButtonDownEvent, new MouseButtonEventHandler(MainChart_MouseLeftButtonDown), true);
// MainChart.AddHandler(C1FlexChart.MouseMoveEvent, new MouseEventHandler(MainChart_MouseMove), true);
// MainChart.AddHandler(C1FlexChart.MouseLeftButtonUpEvent, new MouseButtonEventHandler(MainChart_MouseLeftButtonUp), true);
//}
//private void MainChart_MouseMove(object sender, MouseEventArgs e)
//{
// // when zooming update selection range
// if (zooming)
// {
// var currentPosition = e.GetPosition(MainChart);
// Point ptCurrent = currentPosition;
// // Draw new frame
// DrawReversibleRectangle(ptStart, ptCurrent);
// }
//}
//private void MainChart_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
//{
// ReversibleFrameContainer.Visibility = Visibility.Visible;
// // // Start zooming
// zooming = true;
// // // Save starting point of selection rectangle
// ptStart = e.GetPosition(MainChart);
// MainChart.CaptureMouse();
//}
//private void MainChart_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
//{
// //End zooming
// zooming = false;
// ReversibleFrameContainer.Visibility = Visibility.Collapsed;
// ReversibleFrame.Rect = new Rect();
// var currentPosition = e.GetPosition(MainChart);
// PerformZoom(ptStart, currentPosition);
// //Clean up
// ptStart = new Point();
// MainChart.ReleaseMouseCapture();
//}
//private void PerformZoom(Point ptStart, Point ptLast)
//{
// var p1 = MainChart.PointToData(ptStart);
// var p2 = MainChart.PointToData(ptLast);
// MainChart.BeginUpdate();
// // Update axes with new limits
// MainChart.AxisX.Min = Math.Min(p1.X, p2.X);
// MainChart.AxisY.Min = Math.Min(p1.Y, p2.Y);
// MainChart.AxisX.Max = Math.Max(p1.X, p2.X);
// MainChart.AxisY.Max = Math.Max(p1.Y, p2.Y);
// MainChart.EndUpdate();
//}
//private void DrawReversibleRectangle(Point p1, Point p2)
//{
// // Normalize the rectangle
// var rc = new Rect(Math.Min(p1.X, p2.X), Math.Min(p1.Y, p2.Y),
// Math.Abs(p2.X - p1.X), Math.Abs(p2.Y - p1.Y));
// // Draw the reversible frame
// ReversibleFrame.Rect = rc;
//}
}
}

View File

@@ -0,0 +1,208 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C4821193-52FF-4636-8C91-8FD850C2D3ED}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DTS.Viewer.Graph</RootNamespace>
<AssemblyName>DTS.Viewer.Graph</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SccProjectName>
</SccProjectName>
<SccLocalPath>
</SccLocalPath>
<SccAuxPath>
</SccAuxPath>
<SccProvider>
</SccProvider>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="C1.WPF.4, Version=4.0.20163.541, Culture=neutral, PublicKeyToken=2aa4ec5576d6c3ce, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\Program Files (x86)\ComponentOne\WPF Edition\bin\v4\C1.WPF.4.dll</HintPath>
</Reference>
<Reference Include="C1.WPF.C1Chart.4, Version=4.0.20163.541, Culture=neutral, PublicKeyToken=2aa4ec5576d6c3ce, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\Program Files (x86)\ComponentOne\WPF Edition\bin\v4\C1.WPF.C1Chart.4.dll</HintPath>
</Reference>
<Reference Include="C1.WPF.C1Chart.Extended.4, Version=4.0.20163.541, Culture=neutral, PublicKeyToken=2aa4ec5576d6c3ce, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\Program Files (x86)\ComponentOne\WPF Edition\bin\v4\C1.WPF.C1Chart.Extended.4.dll</HintPath>
</Reference>
<Reference Include="C1.WPF.DX.4, Version=4.0.20163.541, Culture=neutral, PublicKeyToken=2aa4ec5576d6c3ce, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\Program Files (x86)\ComponentOne\WPF Edition\bin\v4\C1.WPF.DX.4.dll</HintPath>
</Reference>
<Reference Include="C1.WPF.Pdf.4, Version=4.0.20181.587, Culture=neutral, PublicKeyToken=2aa4ec5576d6c3ce, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\Program Files (x86)\ComponentOne\WPF Edition\bin\v4\C1.WPF.Pdf.4.dll</HintPath>
</Reference>
<Reference Include="Microsoft.JScript" />
<Reference Include="Microsoft.Xaml.Behaviors">
<HintPath>..\..\..\Common\DTS.Common\lib\PrismLibrary\Microsoft.Xaml.Behaviors.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="Prism">
<HintPath>..\..\..\Common\DTS.Common\lib\PrismLibrary\Prism.dll</HintPath>
</Reference>
<Reference Include="Prism.Unity.Wpf">
<HintPath>..\..\..\Common\DTS.Common\lib\PrismLibrary\Prism.Unity.Wpf.dll</HintPath>
</Reference>
<Reference Include="Prism.Wpf">
<HintPath>..\..\..\Common\DTS.Common\lib\PrismLibrary\Prism.Wpf.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Numerics" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xaml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Unity.Abstractions">
<HintPath>..\..\..\Common\DTS.Common\lib\PrismLibrary\Unity.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Unity.Container">
<HintPath>..\..\..\Common\DTS.Common\lib\PrismLibrary\Unity.Container.dll</HintPath>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="Xceed.Wpf.Toolkit">
<HintPath>..\..\..\Common\DTS.Common\lib\Xceed.Wpf.Toolkit\Xceed.Wpf.Toolkit.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="GraphModule.cs" />
<Compile Include="Model\TestDataSeries.cs" />
<Compile Include="Model\TestDataSeriesModel.cs" />
<Compile Include="Properties\Annotations.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Resources\StringResources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>StringResources.resx</DependentUpon>
</Compile>
<Compile Include="Resources\TranslateExtension.cs" />
<Compile Include="ViewModel\TestDataSeriesViewModel.cs" />
<Compile Include="ViewModel\GraphViewModel.cs" />
<Compile Include="View\GraphView.xaml.cs">
<DependentUpon>GraphView.xaml</DependentUpon>
</Compile>
<Compile Include="View\TestDataSeriesView.xaml.cs">
<DependentUpon>TestDataSeriesView.xaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<Page Include="Resources\CommonStyles.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="View\GraphView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="View\TestDataSeriesView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Properties\Licenses.licx" />
<EmbeddedResource Include="Resources\StringResources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>StringResources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Common\DTS.Common.Core\DTS.Common.Core.csproj">
<Project>{fab1f470-1574-4301-b56e-d3364aa93679}</Project>
<Name>DTS.Common.Core</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\Common\DTS.Common.DAS.Concepts\DTS.Common.DAS.Concepts.csproj">
<Project>{03d8c736-36eb-4cd1-a6d9-130452b23239}</Project>
<Name>DTS.Common.DAS.Concepts</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\Common\DTS.Common.Serialization\DTS.Common.Serialization.csproj">
<Project>{b7d50b14-fa61-4fe4-bff7-b257902b55b0}</Project>
<Name>DTS.Common.Serialization</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\Common\DTS.Common.Utilities\DTS.Common.Utilities.csproj">
<Project>{03eace47-ea59-44ac-b49d-956e4dc4d618}</Project>
<Name>DTS.Common.Utilities</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\Common\DTS.Common\DTS.Common.csproj">
<Project>{114edc77-f3b5-4576-a91b-40818d503b55}</Project>
<Name>DTS.Common</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\DataPRO\ExocortexDSP\Exocortex.DSP.v1.csproj">
<Project>{1904a41b-d1b8-40e5-adbb-728ddcf7c816}</Project>
<Name>Exocortex.DSP.v1</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\DataPRO\FftSharp\FftSharp.csproj">
<Project>{9ff2beb4-a267-4139-a37d-9c9a58d7d36d}</Project>
<Name>FftSharp</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,266 @@
using System;
using System.ComponentModel;
using System.Threading.Tasks;
using C1.WPF.C1Chart;
using DTS.Common.Base;
using DTS.Common.Events;
using DTS.Common.Interactivity;
using DTS.Common.Interface;
using Prism.Events;
using Prism.Regions;
using Unity;
// ReSharper disable InconsistentNaming
// ReSharper disable NotAccessedField.Local
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Local
// ReSharper disable CheckNamespace
// ReSharper disable UnusedAutoPropertyAccessor.Local
// ReSharper disable UnusedMember.Local
// ReSharper disable RedundantDefaultMemberInitializer
namespace DTS.Viewer.Graph
{
public class GraphViewModel : BaseViewModel<IGraphViewModel>, IGraphViewModel
{
public IGraphView View { get; private set; }
internal IBaseViewModel Parent { get; set; }
private new IBaseModel Model { get; set; }
public ITestDataSeriesView DataSeriesView { get; set; }
private IEventAggregator _eventAggregator { get; set; }
private IUnityContainer _unityContainer { get; set; }
public InteractionRequest<Notification> NotificationRequest { get; private set; }
public new InteractionRequest<Confirmation> ConfirmationRequest { get; private set; }
/// <summary>
/// Creates a new instance of the GraphViewModel.
/// </summary>
/// <param name="view">The GraphView interface.</param>
/// <param name="regionManager">The logical placeholder defined within the application's UI (in the shell or within views) into which views are displayed.</param>
/// <param name="eventAggregator">The EventAggregator which allows different components to publish/subscribe to events without being coupled to each other.</param>
/// <param name="unityContainer">The unityContainer.</param>
public GraphViewModel(IGraphView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)
: base(regionManager, eventAggregator, unityContainer)
{
View = view;
View.DataContext = this;
NotificationRequest = new InteractionRequest<Notification>();
ConfirmationRequest = new InteractionRequest<Confirmation>();
_eventAggregator = eventAggregator;
_unityContainer = unityContainer;
}
#region Methods
private void Subscribe()
{
_eventAggregator.GetEvent<RaiseNotification>().Subscribe(OnRaiseNotification);
_eventAggregator.GetEvent<GraphSelectedChannelCountNotification>().Subscribe(OnGraphSelectedCountChanged);
_eventAggregator.GetEvent<TestSummaryCountNotification>().Subscribe(OnTestSelectedCountChanged);
_eventAggregator.GetEvent<TestModificationChangedEvent>().Subscribe(OnTestModificationChanged);
_eventAggregator.GetEvent<GraphChannelsReadCompletedNotification>().Subscribe(OnGraphChannelsReadCompleted, ThreadOption.UIThread);
_eventAggregator.GetEvent<GraphChannelReadCalcProgressChangedEvent>().Subscribe(OnGraphChannelReadCalcProgressChangedEvent, ThreadOption.UIThread);
}
private void SubscribeDataSelect()
{
_eventAggregator.GetEvent<RaiseNotification>().Subscribe(OnRaiseNotification);
_eventAggregator.GetEvent<GraphSelectedChannelCountNotification>().Subscribe(OnGraphSelectedCountChanged);
_eventAggregator.GetEvent<TestSummaryCountNotification>().Subscribe(OnTestSelectedCountChanged);
_eventAggregator.GetEvent<GraphChannelsReadCompletedNotification>().Subscribe(OnGraphChannelsReadCompleted, ThreadOption.UIThread);
_eventAggregator.GetEvent<GraphChannelReadCalcProgressChangedEvent>().Subscribe(OnGraphChannelReadCalcProgressChangedEvent, ThreadOption.UIThread);
}
private void SubscribeResult()
{
_eventAggregator.GetEvent<RaiseNotification>().Subscribe(OnRaiseNotification);
_eventAggregator.GetEvent<GraphSelectedChannelCountNotification>().Subscribe(OnGraphSelectedCountChanged);
_eventAggregator.GetEvent<TestSummaryCountNotification>().Subscribe(OnTestSelectedCountChanged);
_eventAggregator.GetEvent<GraphChannelsReadCompletedNotification>().Subscribe(OnGraphChannelsReadCompleted, ThreadOption.UIThread);
_eventAggregator.GetEvent<GraphChannelReadCalcProgressChangedEvent>().Subscribe(OnGraphChannelReadCalcProgressChangedEvent, ThreadOption.UIThread);
}
private void OnTestModificationChanged(ITestModificationModel obj)
{
}
public override void Initialize()
{
}
public override void Initialize(object parameter)
{
if (parameter is IViewerMainViewModel)
{
Subscribe();
Parent = (IBaseViewModel)parameter;
DataSeriesView = GetTestDataSeriesView(this);
}
else if (parameter is Tuple<IBaseViewModel, string> tuParam && tuParam.Item1 is IPSDReportMainViewModel)
{
switch (tuParam.Item2)
{
case "DataSelect":
SubscribeDataSelect();
break;
default:
SubscribeResult();
break;
}
Parent = tuParam.Item1;
DataSeriesView = GetTestDataSeriesView(this, "Graph" == tuParam.Item2, tuParam.Item2);
switch (tuParam.Item2)
{
case "DataSelect":
//kill scrolling, zoom in/out to data onscreen
((AxisScrollBar)((TestDataSeriesView)DataSeriesView).MainChart.View.AxisX.ScrollBar).Visibility = System.Windows.Visibility.Collapsed;
((AxisScrollBar)((TestDataSeriesView)DataSeriesView).MainChart.View.AxisY.ScrollBar).Visibility = System.Windows.Visibility.Collapsed;
break;
default:
//kills mouse selecting too
((TestDataSeriesView)DataSeriesView).MainChart.Actions.Clear();
((AxisScrollBar)((TestDataSeriesView)DataSeriesView).MainChart.View.AxisX.ScrollBar).Visibility = System.Windows.Visibility.Collapsed;
((AxisScrollBar)((TestDataSeriesView)DataSeriesView).MainChart.View.AxisY.ScrollBar).Visibility = System.Windows.Visibility.Collapsed;
break;
}
}
}
private ITestDataSeriesView GetTestDataSeriesView(IBaseViewModel parent, bool initPSD = false, string chartType = "")
{
var view = _unityContainer.Resolve<ITestDataSeriesView>();
var viewModel = _unityContainer.Resolve<ITestDataSeriesViewModel>();
view.DataContext = viewModel;
viewModel.Initialize(parent, chartType);
if (initPSD)
{
((TestDataSeriesViewModel)viewModel).SubscribePSD();
}
return view;
}
#region Change Events
private const string MessageSelection = "Please select {0}(s) to view data";
private void OnTestSelectedCountChanged(TestSummaryCountNotificationArg arg)
{
if (Parent != arg.ParentVM) return;
const string test = "Test";
const string graph = "Graph";
MessageText = string.Format(MessageSelection, arg.SummaryCount == 0 ? test : graph);
}
/// <summary>
/// Private Event handler for RaiseNotification event.
/// </summary>
private void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle)
{
// Notification object expects a NotificationContentEventArgsWithoutTitle object and a Title string.
var eventArgsWithoutTitle = new NotificationContentEventArgs(eventArgsWithTitle.Message, eventArgsWithTitle.MessageDetails, eventArgsWithTitle.Image);
NotificationRequest.Raise(new Notification
{
Content = eventArgsWithoutTitle,
Title = eventArgsWithTitle.Title
});
}
private void OnGraphSelectedCountChanged(GraphSelectedChannelCountNotificationArg arg)
{
if (Parent != arg?.ParentVM) return;
MessageVisibility = !(arg.SelectedChannelCount > 0);
GraphInfoVisibility = !MessageVisibility;
}
private void OnGraphChannelsReadCompleted(GraphChannelsReadCompletedNotificationArgs arg)
{
if (null == arg) { return; }
if (this != arg.GraphVM) return;
if (!arg.IsReadCompleted)
{
ProgressText = Resources.StringResources.ReadingChannelData;
ProgressPercent = 0;
}
ProgressVisibility = !arg.IsReadCompleted;
}
private void OnGraphChannelReadCalcProgressChangedEvent(GraphChannelReadCalcProgressChangedEventArgs arg)
{
if (this != arg.GraphVM) return;
if (!string.IsNullOrEmpty(arg.ProgressMessage)) ProgressText = arg.ProgressMessage;
if (arg.ProgressPercent >= 0) ProgressPercent = arg.ProgressPercent;
}
#endregion Change Events
#endregion
#region ContextRegion
public object ContextGraphRegion
{
get => ((GraphView)View).GraphRegion.Content;
set { ((GraphView)View).GraphRegion.Content = value; OnPropertyChanged("ContextGraphRegion"); }
}
#endregion
#region Properties
private string _messageText = "Please select Event(s) to export data";
public string MessageText { get => _messageText; set { _messageText = value; OnPropertyChanged("MessageText"); } }
private bool _messageVisibility = true;
public bool MessageVisibility { get => _messageVisibility; set { _messageVisibility = value; FireVisibilities(); } }
private double _progressPercent = 0D;
public double ProgressPercent { get => _progressPercent; set { _progressPercent = value; OnPropertyChanged("ProgressPercent"); } }
private string _progressText = "Reading channel data...";
public string ProgressText { get => _progressText; set { _progressText = value; OnPropertyChanged("ProgressText"); } }
private bool _progressVisibility = false;
public bool ProgressVisibility { get => _progressVisibility; set { _progressVisibility = value; FireVisibilities(); } }
private bool _graphInfoVisibility = false;
public bool GraphInfoVisibility { get => _graphInfoVisibility; set { _graphInfoVisibility = value; FireVisibilities(); } }
public bool GraphVisibility => !MessageVisibility;
///<summary>
///Occurs when a property value changes.
///</summary>
public new event PropertyChangedEventHandler PropertyChanged;
private new void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private void FireVisibilities()
{
OnPropertyChanged("MessageVisibility");
OnPropertyChanged("ProgressVisibility");
OnPropertyChanged("GraphInfoVisibility");
OnPropertyChanged("GraphVisibility");
}
/// <summary>
/// Gets the HeaderInfo.
/// </summary>
public string HeaderInfo => "GraphRegion";
private bool _isBusy = false;
public new bool IsBusy
{
get => _isBusy;
set { _isBusy = value; OnPropertyChanged("IsBusy"); }
}
public new bool IsDirty { get; } = false;
#endregion
}
}

View File

@@ -0,0 +1,156 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace DTS.Viewer.Graph.Resources {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class StringResources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal StringResources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DTS.Viewer.Graph.Resources.StringResources", typeof(StringResources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to The frequency of selected filter class ({0}Hz) results in out of bounds data for at least one channel. Please choose a filter class with a frequency less than half of the data&apos;s sample rate.
///{1}.
/// </summary>
internal static string BadDataFromCustomFilter {
get {
return ResourceManager.GetString("BadDataFromCustomFilter", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to At least one channel contains data whose test filter results in out of bounds data. To view filtered data, please choose a filter with a frequency less than half of the data&apos;s sample rate from Chart Options.
///{0}.
/// </summary>
internal static string BadDataFromTestSetupDefaultFilter {
get {
return ResourceManager.GetString("BadDataFromTestSetupDefaultFilter", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Data in at least one channel is unviewable.
///{0}.
/// </summary>
internal static string BadDataUnfilteredUnknown {
get {
return ResourceManager.GetString("BadDataUnfilteredUnknown", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Reading channel data....
/// </summary>
internal static string ReadingChannelData {
get {
return ResourceManager.GetString("ReadingChannelData", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Error occurred saving chart to PDF.
/// </summary>
internal static string SavePDFError {
get {
return ResourceManager.GetString("SavePDFError", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Chart saved succesfully as {0}{1} and {2}{3}.
/// </summary>
internal static string SavePDFSuccess {
get {
return ResourceManager.GetString("SavePDFSuccess", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Error occurred saving report to CSV.
/// </summary>
internal static string SaveReportCSVError {
get {
return ResourceManager.GetString("SaveReportCSVError", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Report saved to CSV succesfully in {0}.
/// </summary>
internal static string SaveReportCSVSuccess {
get {
return ResourceManager.GetString("SaveReportCSVSuccess", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Error occurred saving report to PDF.
/// </summary>
internal static string SaveReportPDFError {
get {
return ResourceManager.GetString("SaveReportPDFError", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Report saved to PDF succesfully in {0}.
/// </summary>
internal static string SaveReportPDFSuccess {
get {
return ResourceManager.GetString("SaveReportPDFSuccess", resourceCulture);
}
}
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Windows.Markup;
using DTS.Viewer.Graph.Resources;
namespace DTS.Viewer.Graph
{
[MarkupExtensionReturnType(typeof(string))]
public class TranslateExtension : MarkupExtension
{
private readonly string _key;
public TranslateExtension(string key) { _key = key; }
private const string NotFound = "#stringnotfound#";
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (string.IsNullOrEmpty(_key)) { return NotFound; }
return StringResources.ResourceManager.GetString(_key) ?? NotFound + " " + _key;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FftSharp" version="1.1.4" targetFramework="net461" />
<package id="System.Buffers" version="4.5.1" targetFramework="net461" />
<package id="System.Memory" version="4.5.4" targetFramework="net461" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net461" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.3" targetFramework="net461" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net461" requireReinstallation="true" />
</packages>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.4.0" newVersion="4.0.4.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>

View File

@@ -0,0 +1,39 @@
<base:BaseView x:Class="DTS.Viewer.Graph.GraphView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:base="clr-namespace:DTS.Common.Base;assembly=DTS.Common"
xmlns:converters="clr-namespace:DTS.Common.Converters;assembly=DTS.Common"
HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<base:BaseView.Resources>
<ResourceDictionary >
<converters:BooleanToOpacityConverter x:Key="BooleanToOpacityConverter" />
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Resources/CommonStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</base:BaseView.Resources>
<ContentControl x:Name="GraphRegion" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ContentControl.Template>
<ControlTemplate TargetType="ContentControl">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ContentControl Content="{Binding DataSeriesView}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Visibility="{Binding Path=GraphVisibility, Converter={StaticResource BooleanToVisibilityConverter}}" Opacity="{Binding Path=ProgressVisibility, Converter={StaticResource BooleanToOpacityConverter}}" />
<TextBlock Text="{Binding Path=MessageText, FallbackValue='This is a message', Mode=TwoWay}" FontWeight="Bold" FontSize="14" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Visibility="{Binding Path=MessageVisibility, Converter={StaticResource BooleanToVisibilityConverter}, Mode=TwoWay}" TextAlignment="Center" />
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Visibility="{Binding Path=ProgressVisibility, Converter={StaticResource BooleanToVisibilityConverter}, Mode=TwoWay}" >
<TextBlock Text="{Binding Path=ProgressText, FallbackValue='This is a message', Mode=TwoWay}" FontWeight="Bold" FontSize="14" TextAlignment="Center" />
<ProgressBar Value="{Binding Path=ProgressPercent, FallbackValue=0, Mode=TwoWay}" />
</StackPanel>
</Grid>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>
</base:BaseView>

View File

@@ -0,0 +1,141 @@
using System;
using System.Windows.Media.Imaging;
using DTS.Common;
using DTS.Common.Interface;
using DTS.Viewer.Graph;
using Prism.Ioc;
using Prism.Modularity;
using Unity;
// ReSharper disable UnusedParameter.Local
[assembly: GraphNameAttribute()]
[assembly: GraphImageAttribute()]
namespace DTS.Viewer.Graph
{
[Module(ModuleName = "Graph")]
public class GraphModule : IModule
{
/// <summary>
/// Injected unity container
/// </summary>
private readonly IUnityContainer _unityContainer;
/// <summary>
/// Initializes a new instance of the <see cref="GraphModule"/> class.
/// </summary>
/// <param name="unityContainer">Obtained reference of the unity container by using dependency injection.</param>
public GraphModule(IUnityContainer unityContainer)
{
_unityContainer = unityContainer;
}
public void Initialize()
{
// Register View & View-Model with Unity dependency injection container as a singleton.
_unityContainer.RegisterType<IGraphView, GraphView>();
_unityContainer.RegisterType<IGraphViewModel, GraphViewModel>();
//_unityContainer.RegisterType<ITestDataView, TestDataView>();
//_unityContainer.RegisterType<ITestDataViewModel, TestDataViewModel>();
_unityContainer.RegisterType<ITestDataSeriesView, TestDataSeriesView>();
_unityContainer.RegisterType<ITestDataSeriesViewModel, TestDataSeriesViewModel>();
}
public void OnInitialized(IContainerProvider containerProvider)
{
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
Initialize();
}
}
/// <summary>
/// Attribute class contains assembly name
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
public class GraphNameAttribute : TextAttribute
{
private readonly string _assemblyName;
public GraphNameAttribute() : this(null) { }
public GraphNameAttribute(string s)
{
_assemblyName = AssemblyNames.Graph.ToString();
}
public override string AssemblyName => _assemblyName;
public override Type GetAttributeType()
{
return typeof(TextAttribute);
}
public override string GetAssemblyName()
{
return AssemblyName;
}
}
/// <summary>
/// Attribute class contains assembly image and name - used on the Main screen to display available components
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
public class GraphImageAttribute : ImageAttribute
{
private BitmapImage _img;
public GraphImageAttribute() : this(null) { }
public override BitmapImage AssemblyImage
{
get { _img = AssemblyInfo.GetImage(AssemblyNames.Graph.ToString()); return _img; }
}
public GraphImageAttribute(string s)
{
_img = AssemblyInfo.GetImage(AssemblyNames.Graph.ToString());
}
public override Type GetAttributeType()
{
return typeof(ImageAttribute);
}
public override BitmapImage GetAssemblyImage()
{
return AssemblyImage;
}
private string _name;
public override string AssemblyName
{
get { _name = AssemblyNames.Graph.ToString(); return _name; }
}
public override string GetAssemblyName()
{
return AssemblyName;
}
private string _group;
public override string AssemblyGroup
{
get { _group = eAssemblyGroups.Viewer.ToString(); return _group; }
}
public override string GetAssemblyGroup()
{
return AssemblyGroup;
}
private eAssemblyRegion _region;
public override eAssemblyRegion AssemblyRegion
{
get { _region = eAssemblyRegion.GraphRegion; return _region; }
}
public override eAssemblyRegion GetAssemblyRegion()
{
return AssemblyRegion;
}
}
}

View File

@@ -0,0 +1,31 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c1="http://schemas.componentone.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/DTS.Common;component/Themes/brushes.xaml" />
</ResourceDictionary.MergedDictionaries>
<Color x:Key="ColorLightChartBackground" A="#FF" R="#FF" G="#FF" B="#FF"/>
<Color x:Key="ColorLightChartForeground" A="#FF" R="#00" G="#00" B="#00" ScA="1"/>
<SolidColorBrush x:Key="Brush_ChartZoomBackground" Color="#11000000" />
<SolidColorBrush x:Key="BrushChartForeground" Color="{StaticResource ColorLightChartForeground}" />
<SolidColorBrush x:Key="BrushChartBackground" Color="{StaticResource ColorLightChartBackground}" />
<Style x:Key="LineChartAxisStyle" TargetType="c1:Axis">
<Setter Property="Position" Value="DisableLastLabelOverflow" />
</Style>
<Style x:Key="LineChartStyle" TargetType="c1:C1Chart">
<Setter Property="Foreground" Value="{StaticResource BrushChartForeground}" />
<Setter Property="Background" Value="{StaticResource BrushChartBackground}" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="10" />
<Setter Property="Padding" Value="10" />
<Setter Property="ChartType" Value="LineSmoothed" />
<Setter Property="FontFamily" Value="Segoe UI Light" />
<Setter Property="FontSize" Value="14"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="MinHeight" Value="200" />
<Setter Property="MinWidth" Value="300" />
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,241 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using C1.WPF.C1Chart;
using C1.WPF.C1Chart.Extended;
using C1.WPF.Pdf;
using DTS.Common.Interface;
using DTS.Common.Utilities.Logging;
using DTS.Common.Utils;
using KeyEventArgs = System.Windows.Input.KeyEventArgs;
using System.Globalization;
// ReSharper disable CheckNamespace
namespace DTS.Viewer.Graph
{
/// <summary>
/// Interaction logic for TestDataSeriesView.xaml
/// </summary>
public partial class TestDataSeriesView : ITestDataSeriesView
{
public TestDataSeriesView()
{
InitializeComponent();
}
private void obj_DataPointChanged(object sender, EventArgs e)
{
//// update label in code from marker
//if (DataContext == null) return;
//var obj = (ChartPanelObject)sender;
//if (obj == null) return;
//var pt = MainChart.View.PointFromData(obj.DataPoint);
//var txt = String.Empty;
//for (var i = 0; i < MainChart.Data.Children.Count; i++)
//{
// double distance = 0; //distance calculated, but not used
// var index = MainChart.View.DataIndexFromPoint(pt, i, MeasureOption.X, out distance);
// if (index == -1) continue;
// txt += Environment.NewLine + MainChart.Data.Children[i].Label + Environment.NewLine + "Y: " + MainChart.Data.Children[i].GetDataValue("Values", index) + Environment.NewLine + "X: " + MainChart.Data.Children[i].GetDataValue("XValues", index);
//}
//var viewModel = (ITestDataSeriesViewModel)DataContext;
//viewModel.CurrentCursorValues = txt;
}
private void MainChart_OnMouseWheel(object sender, MouseWheelEventArgs e)
{
//if (Keyboard.Modifiers == ModifierKeys.Control && e.Delta == -120)
//{
// MainChart.View.AxisX.Scale += 0.1;
// MainChart.View.AxisY.Scale += 0.1;
//}
//else if (Keyboard.Modifiers == ModifierKeys.Control && e.Delta == 120)
//{
// MainChart.View.AxisX.Scale -= 0.1;
// MainChart.View.AxisY.Scale -= 0.1;
//}
}
private void MainChart_OnKeyUp(object sender, KeyEventArgs e)
{
}
public bool SaveReportToPDF(string directory)
{
try
{
if (string.IsNullOrWhiteSpace(directory)) throw new DirectoryNotFoundException();
var indent = 10;
var spacing = 2;
// FB9152: Migrated from ReviewFile.xaml.cs
// Generate Chart Image
var ms = new MemoryStream();
MainChart.SaveImage(ms, ImageFormat.Png);
var bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = ms;
bi.EndInit();
var wBmp = new WriteableBitmap(bi);
var dataSeries = ((TestDataSeriesViewModel)MainChart.DataContext).GraphDataSeries;
// create and save pdf document
var pdf = new C1PdfDocument
{
Landscape = false,
PaperKind = System.Globalization.RegionInfo.CurrentRegion.IsMetric ? PaperKind.A4 : PaperKind.Letter,
};
var font = new C1.WPF.Pdf.Font(MainChart.FontFamily.Source, MainChart.FontSize);
var pen = new Pen(System.Windows.Media.Colors.Black);
var drawHeight = indent;
// write test info
var testSetup = $"Test Setup: {dataSeries[0].TestSetupName}";
var testId = $"Test ID: {dataSeries[0].TestId}";
pdf.DrawString(testSetup, font, System.Windows.Media.Colors.Black, new Point(indent, drawHeight));
drawHeight += (int)pdf.MeasureString(testSetup, font).Height;
pdf.DrawString(testId, font, System.Windows.Media.Colors.Black, new Point(indent, drawHeight));
drawHeight += (int)pdf.MeasureString(testId, font).Height;
// draw chart
var chartWidth = pdf.PageSize.Width - indent - indent;
var chartHeight = (chartWidth / MainChart.ActualWidth) * MainChart.ActualHeight;
pdf.DrawImage(wBmp, new Rect(indent,
drawHeight,
chartWidth,
chartHeight));
drawHeight += (int)chartHeight;
// write gRMS table
var colStart = indent * 2;
var col1X = colStart + spacing;
var col2X = col1X + dataSeries.Max(ds => pdf.MeasureString(ds.ChannelName, font).Width) + spacing;
var col3X = col2X + Math.Max(pdf.MeasureString("Sample Rate", font).Width, dataSeries.Max(ds => pdf.MeasureString(ds.SampleRate, font).Width)) + spacing;
var colEnd = col3X + dataSeries.Max(ds => pdf.MeasureString(ds.GRMS.ToString(), font).Width) + spacing;
pdf.DrawLine(pen, col1X, drawHeight, colEnd, drawHeight);
pdf.DrawString("Name", font, System.Windows.Media.Colors.Black, new Point(col1X, drawHeight));
pdf.DrawString("Sample Rate", font, System.Windows.Media.Colors.Black, new Point(col2X, drawHeight));
pdf.DrawString("gRMS", font, System.Windows.Media.Colors.Black, new Point(col3X, drawHeight));
var titleHeight = (int)pdf.MeasureString("gRMS", font).Height;
pdf.DrawLine(pen, col1X, drawHeight, col1X, drawHeight + titleHeight);
pdf.DrawLine(pen, col2X, drawHeight, col2X, drawHeight + titleHeight);
pdf.DrawLine(pen, col3X, drawHeight, col3X, drawHeight + titleHeight);
pdf.DrawLine(pen, colEnd, drawHeight, colEnd, drawHeight + titleHeight);
drawHeight += titleHeight;
pdf.DrawLine(pen, col1X, drawHeight, colEnd, drawHeight);
foreach (var ds in dataSeries)
{
var rowHeight = (int)pdf.MeasureString(ds.ChannelName, font).Height;
pdf.FillRectangle((ds.GraphColor as System.Windows.Media.SolidColorBrush).Color, indent, drawHeight, indent, rowHeight);
pdf.DrawString(ds.ChannelName, font, System.Windows.Media.Colors.Black, new Point(col1X, drawHeight));
pdf.DrawString(ds.SampleRate, font, System.Windows.Media.Colors.Black, new Point(col2X, drawHeight));
pdf.DrawString(ds.GRMS.ToString(), font, System.Windows.Media.Colors.Black, new Point(col3X, drawHeight));
pdf.DrawLine(pen, col1X, drawHeight, col1X, drawHeight + rowHeight);
pdf.DrawLine(pen, col2X, drawHeight, col2X, drawHeight + rowHeight);
pdf.DrawLine(pen, col3X, drawHeight, col3X, drawHeight + rowHeight);
pdf.DrawLine(pen, colEnd, drawHeight, colEnd, drawHeight + rowHeight);
drawHeight += rowHeight;
pdf.DrawLine(pen, col1X, drawHeight, colEnd, drawHeight);
}
//pdf.ImageQuality = ImageQuality.High;
var pdfFileName = directory + "\\" +
DateTime.Now.ToString("M'/'d'/'yyyy", CultureInfo.InvariantCulture).Replace("/", "_") + "_" +
DateTime.Now.ToString("h':'mm' 'tt", CultureInfo.InvariantCulture).Replace(":", "_") + "_" + DateTime.Now.Second + "_" +
DateTime.Now.Millisecond + ".pdf";
if (!System.IO.Directory.Exists(directory)) System.IO.Directory.CreateDirectory(directory);
var pdfPath = Path.Combine(directory, pdfFileName);
pdf.Save(pdfPath);
// 35532 log save path after successful write
APILogger.Log($"Report saved to {pdfPath}");
return true;
}
catch (Exception ex)
{
// 35532
APILogger.Log("Error saving report to PDF");
APILogger.LogException(ex);
}
return false;
}
public bool SaveReportToCSV(string directory)
{
try
{
if (!System.IO.Directory.Exists(directory)) System.IO.Directory.CreateDirectory(directory);
var csvFileName = directory + "\\" +
DateTime.Now.ToString("M'/'d'/'yyyy", CultureInfo.InvariantCulture).Replace("/", "_") + "_" +
DateTime.Now.ToString("h':'mm' 'tt", CultureInfo.InvariantCulture).Replace(":", "_") + "_" + DateTime.Now.Second + "_" +
DateTime.Now.Millisecond + ".PSD.csv";
APILogger.Log("opening ", csvFileName);
using (var fs = new FileStream(csvFileName, FileMode.Create))
{
Encoding encoder;
try
{
encoder = Common.Utils.FileUtils.GetEncoding(Encoding.UTF8.CodePage);
}
catch (System.Exception ex)
{
APILogger.Log("Problem getting encoder", ex);
encoder = Encoding.Default;
}
using (var fileWriter = new StreamWriter(fs, encoder, 1024 * 1000))
{
var dataSeries = ((TestDataSeriesViewModel)MainChart.DataContext).GraphDataSeries;
var header = "Frequency," + string.Join(",", dataSeries.Select(ds => ds.ChannelName).ToArray());
fileWriter.WriteLine(header);
var units = "Hz," + string.Join(",", dataSeries.Select(ds => ds.EngineeringUnits + "^2/Hz"));
fileWriter.WriteLine(units);
for (var i = 0; dataSeries.All(ds => i < ds.Xvalue.Length && i < ds.Yvalue.Length); i++)
{
var line = dataSeries[0].Xvalue[i].ToString() + "," + string.Join(",", dataSeries.Select(ds => ds.Yvalue[i].ToString()).ToArray());
fileWriter.WriteLine(line);
}
}
fs.Close();
// 35532 log save path after successful write
APILogger.Log($"Report saved to {csvFileName}");
}
return true;
}
catch (Exception ex)
{
// 35532
APILogger.Log("Error saving report to CSV");
APILogger.LogException(ex);
}
return false;
}
}
public static class AxisExtension
{
public static double GetDispMin(this Axis axis) { return axis.ActualMin + axis.Value * (axis.ActualMax - axis.ActualMin) * (1 - axis.Scale); }
public static double GetDispMax(this Axis axis) { return axis.ActualMax - (1 - axis.Value) * (axis.ActualMax - axis.ActualMin) * (1 - axis.Scale); }
}
}

View File

@@ -0,0 +1,384 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Media;
using DTS.Common.Base;
using DTS.Common.Converters;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Interface;
using DTS.Common.Utils;
using DTS.Common.Utilities;
using DTS.Common.Utilities.Logging;
using DTS.Viewer.Graph.Model;
using DTS.Common.Events;
using Prism.Events;
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
// ReSharper disable UnusedMember.Local
// ReSharper disable UnassignedGetOnlyAutoProperty
namespace DTS.Viewer.Graph
{
public class TestDataSeriesModel : IBaseModel
{
public IGraphViewModel Parent { get; set; }
public IEventAggregator _eventAggregator { get; set; }
private IChartOptionsModel ChartOptions { get; set; }
private string _errorMessage = string.Empty;
public string ErrorMessage { get => _errorMessage; set { _errorMessage = value; OnPropertyChanged("ErrorMessage"); } }
private SetReadCalcProgressValueDelegate ReadCalcProgressDelegate { get; set; }
private void SetReadCalcProgressValue(string message, double progress)
{
_eventAggregator.GetEvent<GraphChannelReadCalcProgressChangedEvent>().Publish(new GraphChannelReadCalcProgressChangedEventArgs() { ProgressMessage = message, ProgressPercent = progress, GraphVM = (GraphViewModel)Parent });
}
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
public async Task<ITestDataSeries> GetTestDataAsync(ITestChannel channel, IChartOptionsModel chartOptions, bool bVolts, IPSDReportSettingsModel psdSettings = null)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
{
return GetTestData(channel, chartOptions, bVolts, psdSettings);
}
#pragma warning disable 1998
public async Task<List<ITestDataSeries>> GetTestDataAsync(List<ITestChannel> channels, IChartOptionsModel chartOptions, bool bVolts, IPSDReportSettingsModel psdSettings = null)
#pragma warning restore 1998
{
var testData = channels.Select(channel =>
{
try
{
chartOptions.IsDigitalChannel = channel.Bridge.StartsWith(Common.Enums.Sensors.SensorConstants.BridgeType.DigitalInput.ToString());
return GetTestData(channel, chartOptions, bVolts, psdSettings);
}
catch (DTS.Common.Exceptions.OutOfDataException ex)
{
throw new Exception($"Failed to read {channel.BinaryFileName} sample {ex.Index}");
}
catch (Exception ex)
{
var msg = $"Failed to read {channel.BinaryFileName}";
APILogger.Log(msg, ex);
throw new Exception(msg);
}
}).ToList();
if (null != psdSettings && psdSettings.ShowEnvelope)
{
testData.Add(GetEnvelopeChannel(testData));
}
return testData;
}
public List<ITestDataSeries> GetTestData(List<ITestChannel> channels, IChartOptionsModel chartOptions, bool bVolts, IPSDReportSettingsModel psdSettings = null)
{
var testData = channels.Select(channel =>
{
try
{
chartOptions.IsDigitalChannel = channel.Bridge.StartsWith(Common.Enums.Sensors.SensorConstants.BridgeType.DigitalInput.ToString());
return GetTestData(channel, chartOptions, bVolts, psdSettings);
}
catch (DTS.Common.Exceptions.OutOfDataException ex)
{
throw new Exception($"Failed to read {channel.BinaryFileName} sample {ex.Index}");
}
catch (Exception ex)
{
var msg = $"Failed to read {channel.BinaryFileName}";
APILogger.Log(msg, ex);
throw new Exception(msg);
}
}).ToList();
if (null != psdSettings && psdSettings.ShowEnvelope)
{
testData.Add(GetEnvelopeChannel(testData));
}
return testData;
}
public ITestDataSeries GetTestData(ITestChannel channel, IChartOptionsModel chartOptions, bool bVolts, IPSDReportSettingsModel psdSettings = null)
{
return AddTestChannelToChart(channel, chartOptions, bVolts, psdSettings);
}
private const string IEPE_BRIDGE = "IEPE";
public TestDataSeries AddTestChannelToChart(ITestChannel channel, IChartOptionsModel chartOptions, bool bVolts, IPSDReportSettingsModel psdSettings = null)
{
if (!string.IsNullOrEmpty(channel.ErrorMessage)) return null;
if (null == ReadCalcProgressDelegate) ReadCalcProgressDelegate = SetReadCalcProgressValue;
//keep FFT always unfiltered
if (chartOptions.UnitType == Common.Enums.Viewer.ChartUnitTypeEnum.FFT || chartOptions.UnitType == Common.Enums.Viewer.ChartUnitTypeEnum.PSD)
{
channel.SoftwareFilter = "none";
}
var channelData = Serialization.SliceRaw.File.Reader.ReadChannelsBinaryData(channel,
out var frequencies, out var peakMagnitude, out var peakFrequency,
ChannelFilter.AdHoc, chartOptions, bVolts, ReadCalcProgressDelegate);
if (!string.IsNullOrEmpty(channel.ErrorMessage)) return null;
//try to get a translated version of the recording mode
var recordingModeString = channel.ParentModule.RecordingMode;
try
{
if (Enum.TryParse(channel.ParentModule.RecordingMode, out DFConstantsAndEnums.RecordingMode mode))
{
var recordingMode = RecordingModeExtensions.ToRecordingModes(mode);
recordingModeString = EnumDescriptionTypeConverter.GetEnumDescription(recordingMode);
}
}
catch (Exception) { }
var chData = new TestDataSeries()
{
TestGroup = channel.Group,
TestId = channel.TestId,
TestSetupName = channel.TestSetupName,
ChannelId = channel.ChannelId,
GroupName = channel.ChannelGroupName,
HardwareChannel = channel.HardwareChannelName,
Bridge = channel.Bridge,
SWAAF = channel.SoftwareFilter,
HWAAF = channel.ParentModule.AaFilterRateHz.ToString(CultureInfo.CurrentCulture),
SampleRate = channel.ParentModule.SampleRateHz.ToString(CultureInfo.CurrentCulture),
RecordingMode = recordingModeString,
ISOCode = channel.IsoCode,
ISOChannelName = channel.IsoChannelName,
UserCode = channel.UserCode,
UserChannelName = channel.UserChannelName,
ChannelName = channel.ChannelName2,
Description = channel.Description,
SensorSN = channel.SerialNumber,
Excitation = channel.Bridge == IEPE_BRIDGE ? "---" : channel.MeasuredExcitationVoltage.ToString("N3"),
Polarity = channel.SensorPolarity,
EngineeringUnits = channel.Eu
};
var y = new List<double>((int)channelData[1].Length);
var x = new List<double>((int)channelData[0].Length);
var curSample = 0;
var timeMultiplier = Convert.ToDecimal(chartOptions.TimeUnitType == Common.Enums.Viewer.TimeUnitTypeEnum.MS ? 1000D : 1D);
if (chartOptions.UnitType == Common.Enums.Viewer.ChartUnitTypeEnum.FFT && null == psdSettings) //FFT (and also not PSD)
{
chData.FFT = true;
chData.PeakFrequency = peakFrequency;
chData.PeakMagnitude = peakMagnitude;
chData.Xvalue = channelData[0];
chData.Yvalue = channelData[1];
chData.SetStatsFromYValues();
}
else if (null == psdSettings) //regular data?
{
chData.FFT = false;
var timeZeroIndex = channel.ParentModule.TriggerSampleNumbers.Count != 0
? channel.ParentModule.TriggerSampleNumbers[0]
: 0;
var timeUnitRatio = channel.ParentModule.SampleRateHz / timeMultiplier;
var startingSample = (int)timeZeroIndex - channel.ParentModule.StartRecordSampleNumber;
if (channel.HIC != 0 && channel.T2Sample > 0)
{
chData.HIC = true;
chData.HICValue = channel.HIC.ToString("N2");
var time1 = (channel.T1Sample - (double)startingSample) / channel.SampleRateHz;
var time2 = (channel.T2Sample - (double)startingSample) / channel.SampleRateHz;
chData.T1Time = (time1 * 1000).ToString("N4");
chData.T2Time = (time2 * 1000).ToString("N4");
}
chData.Xvalue = channelData[0].Select(val => Convert.ToDouble((decimal)val * timeMultiplier)).ToArray();
chData.Yvalue = channelData[1];
chData.SetStatsFromChannel(channel);
}
else //PSD
{
_eventAggregator.GetEvent<GraphChannelReadCalcProgressChangedEvent>().Publish(new GraphChannelReadCalcProgressChangedEventArgs()
{ GraphVM = Parent, ProgressMessage = DTS.Common.Strings.Strings.GeneratingPSD_ResizingData, ProgressPercent = 0 });
var timeZeroIndex = channel.ParentModule.TriggerSampleNumbers.Count != 0
? channel.ParentModule.TriggerSampleNumbers[0]
: 0;
var timeUnitRatio = channel.ParentModule.SampleRateHz / timeMultiplier;
var startingSample = (int)timeZeroIndex - channel.ParentModule.StartRecordSampleNumber;
//Apply PSD Settings
//Step 1: trim data to selected range
var selectStart = (int)(startingSample + psdSettings.DataStart * (double)timeUnitRatio);
var selectEnd = (int)(startingSample + psdSettings.DataEnd * (double)timeUnitRatio);
if (selectEnd > selectStart)
{
channelData[0] = channelData[0].Skip(selectStart).Take(selectEnd - selectStart).ToArray();
channelData[1] = channelData[1].Skip(selectStart).Take(selectEnd - selectStart).ToArray();
}
else
{
selectEnd = curSample;
}
_eventAggregator.GetEvent<GraphChannelReadCalcProgressChangedEvent>().Publish(new GraphChannelReadCalcProgressChangedEventArgs()
{ GraphVM = Parent, ProgressMessage = string.Empty, ProgressPercent = 50 });
//Step 2: get window type
FftSharp.WindowType type;
switch (psdSettings.WindowType)
{
case Common.Enums.Viewer.Reports.WindowType.Rectangle:
type = FftSharp.WindowType.Rectangular;
break;
case Common.Enums.Viewer.Reports.WindowType.Hamming:
type = FftSharp.WindowType.Hamming;
break;
case Common.Enums.Viewer.Reports.WindowType.Blackman:
type = FftSharp.WindowType.Blackman;
break;
case Common.Enums.Viewer.Reports.WindowType.BlackmanHarris:
type = FftSharp.WindowType.BlackmanHarris;
break;
case Common.Enums.Viewer.Reports.WindowType.FlatTop:
type = FftSharp.WindowType.FlatTop;
break;
case Common.Enums.Viewer.Reports.WindowType.Hanning:
default:
type = FftSharp.WindowType.Hanning;
break;
}
FftSharp.WindowAveragingType averagingType;
switch (psdSettings.WindowAveragingType)
{
case Common.Enums.Viewer.Reports.WindowAveragingType.PeakHoldMax:
averagingType = FftSharp.WindowAveragingType.PeakHoldMax;
break;
case Common.Enums.Viewer.Reports.WindowAveragingType.PeakHoldMin:
averagingType = FftSharp.WindowAveragingType.PeakHoldMin;
break;
case Common.Enums.Viewer.Reports.WindowAveragingType.Averaging:
default:
averagingType = FftSharp.WindowAveragingType.Averaging;
break;
}
//Step 3: ffts require input length be an even power of 2
var next = Utils.GetEnclosingPower2(channelData[1].Length);
var values = channelData[1];
if (values.Length < next)
{
Array.Resize(ref values, next);
}
_eventAggregator.GetEvent<GraphChannelReadCalcProgressChangedEvent>().Publish(new GraphChannelReadCalcProgressChangedEventArgs()
{ GraphVM = Parent, ProgressMessage = string.Empty, ProgressPercent = 100 });
////Step 4: apply a band pass on the input if requested
_eventAggregator.GetEvent<GraphChannelReadCalcProgressChangedEvent>().Publish(new GraphChannelReadCalcProgressChangedEventArgs()
{ GraphVM = Parent, ProgressMessage = DTS.Common.Strings.Strings.GeneratingPSD_ApplyingFilters, ProgressPercent = 0 });
if (psdSettings.LowPassFilterEnabled)
{
values = Exocortex.DSP.PassFilter.LowPass(values, channel.ParentModule.SampleRateHz, (double)psdSettings.LowPassFilterFrequency, (Exocortex.DSP.PassFilterType)psdSettings.LowPassFilterType, (uint)psdSettings.LowPassFilterOrder);
}
if (psdSettings.HighPassFilterEnabled)
{
values = Exocortex.DSP.PassFilter.HighPass(values, channel.ParentModule.SampleRateHz, (double)psdSettings.HighPassFilterFrequency, (Exocortex.DSP.PassFilterType)psdSettings.HighPassFilterType, (uint)psdSettings.HighPassFilterOrder);
}
_eventAggregator.GetEvent<GraphChannelReadCalcProgressChangedEvent>().Publish(new GraphChannelReadCalcProgressChangedEventArgs()
{ GraphVM = Parent, ProgressMessage = string.Empty, ProgressPercent = 100 });
//Step 5: get the PSD
_eventAggregator.GetEvent<GraphChannelReadCalcProgressChangedEvent>().Publish(new GraphChannelReadCalcProgressChangedEventArgs()
{ GraphVM = Parent, ProgressMessage = DTS.Common.Strings.Strings.GeneratingPSD, ProgressPercent = 0 });
var psd = FftSharp.Transform.PSD_Welch(values, channel.ParentModule.SampleRateHz, type, (int)psdSettings.WindowWidth, (int)psdSettings.WindowOverlappingPercent, averagingType, ReadCalcProgressDelegate);
var freq = FftSharp.Transform.FFTfreq(channel.ParentModule.SampleRateHz, psd.Length);
freq[0] = 1;
_eventAggregator.GetEvent<GraphChannelReadCalcProgressChangedEvent>().Publish(new GraphChannelReadCalcProgressChangedEventArgs()
{ GraphVM = Parent, ProgressMessage = string.Empty, ProgressPercent = 100 });
//Step 6: Calculate GRMS
//math from https://blog.endaq.com/why-the-power-spectral-density-psd-is-the-gold-standard-of-vibration-analysis#Benefits
chData.GRMS = CalculateGRMS(freq, psd);
chData.Yvalue = psd;
chData.Xvalue = freq;
chData.FFT = true;
chData.SetStatsFromYValues();
}
channel.Xmax = chData.Xvalue.Max();
channel.Xmin = chData.Xvalue.Min();
chData.GraphColor = new SolidColorBrush(channel.ChannelColor == Colors.Transparent ? Colors.Blue : channel.ChannelColor);
return chData;
}
private ITestDataSeries GetEnvelopeChannel(List<ITestDataSeries> data)
{
if (null == data || data.Count == 0) return new TestDataSeries();
//Create blank-ish data series but set to envelope
var chData = new TestDataSeries
{
TestGroup = DTS.Common.Strings.Strings.EnvelopeUnique,
TestId = data[0].TestId,
TestSetupName = data[0].TestSetupName,
ChannelId = DTS.Common.Strings.Strings.EnvelopeUnique,
GroupName = DTS.Common.Strings.Strings.EnvelopeUnique,
HardwareChannel = DTS.Common.Strings.Strings.EnvelopeUnique,
Bridge = DTS.Common.Strings.Strings.Table_NA,
SWAAF = DTS.Common.Strings.Strings.Table_NA,
HWAAF = DTS.Common.Strings.Strings.Table_NA,
SampleRate = data[0].SampleRate,
RecordingMode = string.Empty,
ISOCode = string.Empty,
ISOChannelName = string.Empty,
UserCode = string.Empty,
UserChannelName = string.Empty,
ChannelName = DTS.Common.Strings.Strings.Envelope,
Description = DTS.Common.Strings.Strings.Envelope,
SensorSN = DTS.Common.Strings.Strings.Envelope,
Excitation = DTS.Common.Strings.Strings.Table_NA,
Polarity = DTS.Common.Strings.Strings.Table_NA
};
//freq series is the same
var freq = data[0].Xvalue.ToList();
//now get the max value at each frequency (the "envelope")
var psd = new List<double>();
for (var i = 0; i < data[0].Yvalue.Length; i++)
{
psd.Add(data.Max(tds => tds.Yvalue[i]));
}
//calculate GRMS of this new "channel"
chData.GRMS = CalculateGRMS(freq.ToArray(), psd.ToArray());
chData.Yvalue = psd.ToArray();
chData.Xvalue = freq.ToArray();
chData.FFT = true;
chData.GraphColor = new SolidColorBrush(Colors.Black);
return chData;
}
private double CalculateGRMS(double[] freq, double[] psd)
{
var aRMS = new List<double>();
for (var i = 0; i < psd.Length - 2 && i < freq.Length - 2; i++)
{
var N = Math.Log10(psd[i + 1] / psd[i]) / Math.Log10(freq[i + 1] / freq[i]);
var ai = N.EqualsDigitPrecision(-1, 1) ?
(psd[i] * freq[i]) * Math.Log(freq[i + 1] / freq[i]) :
(psd[i] / Math.Pow(freq[i], N)) * (1 / (N + 1)) * (Math.Pow(freq[i + 1], N + 1) - Math.Pow(freq[i], N + 1));
if (!double.IsNaN(ai) && !double.IsInfinity(ai)) aRMS.Add(ai);
}
return Math.Sqrt(aRMS.Sum());
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }
public bool IsSaved { get; }
}
}

View File

@@ -0,0 +1,153 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="BadDataFromCustomFilter" xml:space="preserve">
<value>The frequency of selected filter class ({0}Hz) results in out of bounds data for at least one channel. Please choose a filter class with a frequency less than half of the data's sample rate.
{1}</value>
</data>
<data name="BadDataFromTestSetupDefaultFilter" xml:space="preserve">
<value>At least one channel contains data whose test filter results in out of bounds data. To view filtered data, please choose a filter with a frequency less than half of the data's sample rate from Chart Options.
{0}</value>
</data>
<data name="BadDataUnfilteredUnknown" xml:space="preserve">
<value>Data in at least one channel is unviewable.
{0}</value>
</data>
<data name="ReadingChannelData" xml:space="preserve">
<value>Reading channel data...</value>
</data>
<data name="SavePDFError" xml:space="preserve">
<value>Error occurred saving chart to PDF</value>
</data>
<data name="SavePDFSuccess" xml:space="preserve">
<value>Chart saved succesfully as {0}{1} and {2}{3}</value>
</data>
<data name="SaveReportCSVError" xml:space="preserve">
<value>Error occurred saving report to CSV</value>
</data>
<data name="SaveReportCSVSuccess" xml:space="preserve">
<value>Report saved to CSV succesfully in {0}</value>
</data>
<data name="SaveReportPDFError" xml:space="preserve">
<value>Error occurred saving report to PDF</value>
</data>
<data name="SaveReportPDFSuccess" xml:space="preserve">
<value>Report saved to PDF succesfully in {0}</value>
</data>
</root>

View File

@@ -0,0 +1,58 @@
<base:BaseView x:Class="DTS.Viewer.Graph.TestDataView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:base="clr-namespace:DTS.Common.Base;assembly=DTS.Common"
xmlns:c1="http://schemas.componentone.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:converters="clr-namespace:DTS.Common.Converters;assembly=DTS.Common"
xmlns:behaviors="clr-namespace:DTS.Common.Behaviors;assembly=DTS.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:graph="clr-namespace:DTS.Viewer.Graph"
mc:Ignorable="d"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" d:DataContext="{d:DesignInstance graph:TestDataViewModel}">
<base:BaseView.Resources>
<ResourceDictionary >
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Resources/CommonStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</base:BaseView.Resources>
<Grid x:Name="GraphView" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<c1:C1FlexChart x:Name="MainChart" ChartType="Line" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
ToolTipContent="{} Channel: {seriesName}&#13;Time: {x}&#13;Y: {y}" ScrollViewer.HorizontalScrollBarVisibility="Visible" >
<i:Interaction.Behaviors>
<behaviors:MouseCaptureBehavior Proxy="{Binding}" />
</i:Interaction.Behaviors>
<!--<c1:C1FlexChart.ContextMenu >
<ContextMenu>
<MenuItem Header="Create Marker" Command="{Binding CreateMarkerCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Self}}" Visibility="{Binding Path=ShowCursor, Converter={StaticResource BooleanToVisibilityConverter}}" />
</ContextMenu>
</c1:C1FlexChart.ContextMenu>-->
</c1:C1FlexChart>
<Canvas x:Name="ReversibleFrameContainer" Visibility="Collapsed" Background="Transparent" IsHitTestVisible="False">
<Path IsHitTestVisible="False" StrokeDashArray="2, 2" Stroke="Black">
<Path.Data>
<RectangleGeometry x:Name="ReversibleFrame"/>
</Path.Data>
</Path>
</Canvas>
</Grid>
</base:BaseView>

View File

@@ -0,0 +1 @@
C1.WPF.C1Chart.C1Chart, C1.WPF.C1Chart.4

View File

@@ -0,0 +1,16 @@
using DTS.Common.Interface;
// ReSharper disable CheckNamespace
namespace DTS.Viewer.Graph
{
/// <summary>
/// Interaction logic for GraphView.xaml
/// </summary>
public partial class GraphView : IGraphView
{
public GraphView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Graph")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Graph")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("61261c58-c32e-4dea-a87a-d7f956f28b4d")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,313 @@
<base:BaseView x:Class="DTS.Viewer.Graph.TestDataSeriesView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:base="clr-namespace:DTS.Common.Base;assembly=DTS.Common"
xmlns:c1="http://schemas.componentone.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:converters="clr-namespace:DTS.Common.Converters;assembly=DTS.Common"
mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="800"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" x:Name="testDataSeriesView">
<base:BaseView.Resources>
<ResourceDictionary >
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Resources/CommonStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style TargetType="TextBlock" x:Key="OverlayStyle">
<Setter Property="FontSize" Value="12"/>
<Setter Property="Foreground" Value="#D0000000"/>
</Style>
<converters:BooleanToVisibilityConverter x:Key="BoolToVisConverter" />
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBoolToVisConverter" />
</ResourceDictionary>
</base:BaseView.Resources>
<Grid x:Name="GraphViewGrid" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<c1:C1Chart x:Name="MainChart" Style="{DynamicResource LineChartStyle}" Margin="0"
MouseWheel="MainChart_OnMouseWheel" IsManipulationEnabled="True" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="ActionLeave">
<i:InvokeCommandAction Command="{Binding ActionLeaveCommand}" CommandParameter="{Binding ElementName=MainChart}"/>
</i:EventTrigger>
<i:EventTrigger EventName="ActionEnter">
<i:InvokeCommandAction Command="{Binding ActionEnterCommand}" CommandParameter="{Binding ElementName=MainChart}"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseUp">
<i:InvokeCommandAction Command="{Binding MouseUpCommand}" CommandParameter="{Binding ElementName=MainChart}"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseDown">
<i:InvokeCommandAction Command="{Binding MouseDownCommand}" CommandParameter="{Binding ElementName=MainChart}"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseMove">
<i:InvokeCommandAction Command="{Binding MouseMoveCommand}" CommandParameter="{Binding ElementName=MainChart}"/>
</i:EventTrigger>
<i:EventTrigger EventName="GotFocus">
<i:InvokeCommandAction Command="{Binding GotFocusCommand}" CommandParameter="{Binding ElementName=MainChart}"/>
</i:EventTrigger>
<i:EventTrigger EventName="KeyUp">
<i:InvokeCommandAction Command="{Binding ChartOnKeyUpCommand}" />
</i:EventTrigger>
<!--<i:EventTrigger EventName="KeyUp">
<ei:CallMethodAction MethodName="{Binding ChartOnKeyUpMethod}" TargetObject="{Binding}"/>
</i:EventTrigger>-->
</i:Interaction.Triggers>
<c1:LineAreaOptions.OptimizationRadius>5</c1:LineAreaOptions.OptimizationRadius>
<c1:C1Chart.Actions>
<c1:ZoomAction Fill="{StaticResource Brush_ChartZoomBackground}" Stroke="{x:Null}" Block.IsHyphenationEnabled="False"/>
<c1:TranslateAction Modifiers="Shift" />
<c1:ScaleAction Modifiers="Control" />
</c1:C1Chart.Actions>
<c1:C1Chart.View >
<c1:ChartView Focusable="True">
<c1:ChartView.AxisX>
<c1:Axis Style="{DynamicResource LineChartAxisStyle}" MajorGridStroke="#30000000" MajorGridStrokeThickness="1">
<c1:Axis.ScrollBar>
<c1:AxisScrollBar Margin="0,10,0,0" />
</c1:Axis.ScrollBar>
</c1:Axis>
</c1:ChartView.AxisX>
<c1:ChartView.AxisY>
<c1:Axis Style="{DynamicResource LineChartAxisStyle}" MajorGridStroke="#30000000" MajorGridStrokeThickness="1">
<c1:Axis.ScrollBar>
<c1:AxisScrollBar Margin="0,10,0,0"/>
</c1:Axis.ScrollBar>
</c1:Axis>
</c1:ChartView.AxisY>
<!-- Markers layer -->
<c1:ChartView.Layers>
<c1:ChartPanel Visibility="{Binding Path=MarkerVisibilty}" >
<!-- vertical line and dot markers -->
<c1:ChartPanelObject x:Name="Label"
Attach="DataX"
Action="MouseMove"
DataPoint="0,0"
HorizontalAlignment="Left"
VerticalAlignment="Bottom" RenderTransformOrigin="0.5,0.5">
<c1:ChartPanelObject.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform X="5"/>
<TranslateTransform Y="-5"/>
</TransformGroup>
</c1:ChartPanelObject.RenderTransform>
<Grid DataContext="{Binding RelativeSource={x:Static RelativeSource.Self},Path=Parent}">
<Rectangle Fill="Transparent" Opacity=".95" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
<StackPanel Margin="5,2" Orientation="Horizontal">
<!-- ReSharper disable once Xaml.BindingWithContextNotResolved -->
<TextBlock x:Name="LabelY" Text="{Binding DataPoint.Y, StringFormat=F3}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Text=" @ " VerticalAlignment="Center" HorizontalAlignment="Center"/>
<!-- ReSharper disable once Xaml.BindingWithContextNotResolved -->
<TextBlock x:Name="LabelX" Text="{Binding DataPoint.X, StringFormat=F3}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock x:Name="LabelTimeUnits" Text="ms" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</StackPanel>
</Grid>
</c1:ChartPanelObject>
<c1:ChartPanelObject x:Name="Dot"
Attach="DataX"
Action="MouseMove"
DataPoint="0,0"
DataPointChanged="obj_DataPointChanged"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Ellipse Fill="#55FFFFFF" Stroke="Black" StrokeThickness=".5" Width="10" Height="10" />
</c1:ChartPanelObject>
</c1:ChartPanel>
</c1:ChartView.Layers>
</c1:ChartView>
</c1:C1Chart.View>
<c1:C1ChartLegend Grid.Row="1" x:Name="Legend" Visibility="Collapsed" Foreground="{DynamicResource Brush_ChartForeground}"/>
</c1:C1Chart>
<Grid HorizontalAlignment="Right" Background="#D0FFFFFF" VerticalAlignment="Top"
Margin="10" Visibility="{Binding OverlayVisibility}"
Width="300">
<Grid.Style>
<Style TargetType="Grid">
<Style.Triggers>
<EventTrigger RoutedEvent="Control.MouseEnter">
<BeginStoryboard>
<Storyboard >
<DoubleAnimation Duration="0:0:0.2" To="0" Storyboard.TargetProperty="Opacity"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Control.MouseLeave">
<BeginStoryboard>
<Storyboard >
<DoubleAnimation Duration="0:0:0.2" To="1" Storyboard.TargetProperty="Opacity"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Test Setup: " Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding TestSetupName}" Style="{StaticResource OverlayStyle}" TextWrapping="Wrap"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Test Id: " Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding TestId}" Style="{StaticResource OverlayStyle}" TextWrapping="Wrap"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="Group Name: " Style="{StaticResource OverlayStyle}" Visibility="Collapsed"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding GroupName}" Style="{StaticResource OverlayStyle}" Visibility="Collapsed"/>
<TextBlock Grid.Row="3" Grid.Column="0" Text="Hardware Channel: " Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="3" Grid.Column="1" Text="{Binding HardwareChannel}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="4" Grid.Column="0" Text="Serial Number: " Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="4" Grid.Column="1" Text="{Binding SensorSN}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="5" Grid.Column="0" Text="Channel Description: " Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="5" Grid.Column="1" Text="{Binding Description}" Style="{StaticResource OverlayStyle}" TextWrapping="Wrap"/>
<TextBlock Grid.Row="6" Grid.Column="0" Text="Channel User Code: " Style="{StaticResource OverlayStyle}" Visibility="{Binding UserVisibility}"/>
<TextBlock Grid.Row="6" Grid.Column="1" Text="{Binding UserCode}" Style="{StaticResource OverlayStyle}" TextWrapping="Wrap" Visibility="{Binding UserVisibility}"/>
<TextBlock Grid.Row="7" Grid.Column="0" Text="Channel User Name: " Style="{StaticResource OverlayStyle}" Visibility="{Binding UserVisibility}"/>
<TextBlock Grid.Row="7" Grid.Column="1" Text="{Binding UserChannelName}" Style="{StaticResource OverlayStyle}" TextWrapping="Wrap" Visibility="{Binding UserVisibility}"/>
<TextBlock Grid.Row="8" Grid.Column="0" Text="Channel ISO Code: " Style="{StaticResource OverlayStyle}" Visibility="{Binding ISOVisibility}"/>
<TextBlock Grid.Row="8" Grid.Column="1" Text="{Binding ISOCode}" Style="{StaticResource OverlayStyle}" TextWrapping="Wrap" Visibility="{Binding ISOVisibility}"/>
<TextBlock Grid.Row="9" Grid.Column="0" Text="Channel ISO Name: " Style="{StaticResource OverlayStyle}" Visibility="{Binding ISOVisibility}"/>
<TextBlock Grid.Row="9" Grid.Column="1" Text="{Binding ISOChannelName}" Style="{StaticResource OverlayStyle}" TextWrapping="Wrap" Visibility="{Binding ISOVisibility}"/>
<TextBlock Grid.Row="10" Grid.Column="0" Text="Channel Name: " Style="{StaticResource OverlayStyle}" Visibility="{Binding ChannelNameOnlyVisibility}"/>
<TextBlock Grid.Row="10" Grid.Column="1" Text="{Binding UserChannelName}" Style="{StaticResource OverlayStyle}" TextWrapping="Wrap" Visibility="{Binding ChannelNameOnlyVisibility}"/>
<TextBlock Grid.Row="11" Grid.Column="0" Text="Recording Mode: " Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="11" Grid.Column="1" Text="{Binding RecordingMode}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="12" Grid.Column="0" Text="Sample Rate (Hz): " Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="12" Grid.Column="1" Text="{Binding SampleRate}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="13" Grid.Column="0" Text="Hardware Filter (Hz): " Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="13" Grid.Column="1" Text="{Binding HWAAF}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="14" Grid.Column="0" Text="Software Filter Class: " Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="14" Grid.Column="1" Text="{Binding SWAAF}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="15" Grid.Column="0" Text="Excitation (V): " Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="15" Grid.Column="1" Text="{Binding Excitation}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Grid.Row="16" Grid.Column="0" Text="Polarity: " Style="{StaticResource OverlayStyle}" Visibility="{Binding PolarityVisibility}"/>
<TextBlock Grid.Row="16" Grid.Column="1" Text="{Binding Polarity}" Style="{StaticResource OverlayStyle}" Visibility="{Binding PolarityVisibility}"/>
<Rectangle Grid.Row="17" Grid.ColumnSpan="2" Fill="#60000000" StrokeDashArray="" Height="1" Margin="5"/>
<StackPanel Grid.Row="18" Grid.Column="0" Orientation="Horizontal">
<TextBlock Text="Min/Max (" Style="{StaticResource OverlayStyle}"/>
<TextBlock Text="{Binding TitleY}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Text=") :" Style="{StaticResource OverlayStyle}"/>
</StackPanel>
<StackPanel Grid.Row="18" Grid.Column="1" Orientation="Horizontal">
<TextBlock Text="{Binding MinY}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Text="/" Style="{StaticResource OverlayStyle}"/>
<TextBlock Text="{Binding MaxY}" Style="{StaticResource OverlayStyle}"/>
</StackPanel>
<StackPanel Grid.Row="19" Grid.Column="0" Orientation="Horizontal">
<TextBlock Text="Average (" Style="{StaticResource OverlayStyle}"/>
<TextBlock Text="{Binding TitleY}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Text=") :" Style="{StaticResource OverlayStyle}"/>
</StackPanel>
<TextBlock Grid.Row="19" Grid.Column="1" Text="{Binding AvgY}" Style="{StaticResource OverlayStyle}"/>
<StackPanel Grid.Row="20" Grid.Column="0" Orientation="Horizontal">
<TextBlock Text="StdDev (" Style="{StaticResource OverlayStyle}"/>
<TextBlock Text="{Binding TitleY}" Style="{StaticResource OverlayStyle}"/>
<TextBlock Text=") :" Style="{StaticResource OverlayStyle}"/>
</StackPanel>
<TextBlock Grid.Row="20" Grid.Column="1" Text="{Binding StdDevY}" Style="{StaticResource OverlayStyle}"/>
<!-- T0 Value -->
<StackPanel Grid.Row="21" Grid.Column="0" Orientation="Horizontal" Visibility="{Binding FFT, Converter={StaticResource InverseBoolToVisConverter}}">
<TextBlock Text="Value @ T0 (" Style="{StaticResource OverlayStyle}"/>
<TextBlock Text="{Binding TitleY}" Style="{StaticResource OverlayStyle}" />
<TextBlock Text=") :" Style="{StaticResource OverlayStyle}" />
</StackPanel>
<TextBlock Grid.Row="21" Grid.Column="1" Text="{Binding T0EUValue}" Style="{StaticResource OverlayStyle}"
Visibility="{Binding FFT, Converter={StaticResource InverseBoolToVisConverter}}" />
<!-- Cursor Value -->
<StackPanel Grid.Row="22" Grid.Column="0" Orientation="Horizontal" Visibility="{Binding FFT, Converter={StaticResource InverseBoolToVisConverter}}">
<TextBlock Text="Cursor - " Style="{StaticResource OverlayStyle}"/>
</StackPanel>
<TextBlock Grid.Row="22" Grid.Column="1" Text="{Binding CursorValue}" Style="{StaticResource OverlayStyle}"
Visibility="{Binding FFT, Converter={StaticResource InverseBoolToVisConverter}}" />
<!-- Peek Frequency -->
<StackPanel Grid.Row="22" Grid.Column="0" Orientation="Horizontal" Visibility="{Binding FFT, Converter={StaticResource BoolToVisConverter}}">
<TextBlock Text="Peak Magnitude " Style="{StaticResource OverlayStyle}"/>
<TextBlock Text="{Binding PeakMagnitude,StringFormat=N2}" Style="{StaticResource OverlayStyle}" />
<TextBlock Text=" (dB) @ " />
</StackPanel>
<StackPanel Grid.Row="22" Grid.Column="1" Orientation="Horizontal" Visibility="{Binding FFT, Converter={StaticResource BoolToVisConverter}}">
<TextBlock Text="{Binding PeakFrequency,StringFormat=N2}" Style="{StaticResource OverlayStyle}" />
<TextBlock Text=" (Hz)" />
</StackPanel>
<!-- HIC Value -->
<StackPanel Grid.Row="23" Grid.Column="0" Orientation="Horizontal" Visibility="{Binding HIC, Converter={StaticResource BoolToVisConverter}}">
<TextBlock Text="HIC :" Style="{StaticResource OverlayStyle}" />
</StackPanel>
<TextBlock Grid.Row="23" Grid.Column="1" Text="{Binding HICValue}" Style="{StaticResource OverlayStyle}" Visibility="{Binding HIC, Converter={StaticResource BoolToVisConverter}}" />
<!-- T1 Value -->
<StackPanel Grid.Row="24" Grid.Column="0" Orientation="Horizontal" Visibility="{Binding HIC, Converter={StaticResource BoolToVisConverter}}">
<TextBlock Text="T1 (ms) :" Style="{StaticResource OverlayStyle}"/>
</StackPanel>
<TextBlock Grid.Row="24" Grid.Column="1" Text="{Binding T1Time}" Style="{StaticResource OverlayStyle}" Visibility="{Binding HIC, Converter={StaticResource BoolToVisConverter}}"/>
<!-- T2 Value -->
<StackPanel Grid.Row="25" Grid.Column="0" Orientation="Horizontal" Visibility="{Binding HIC, Converter={StaticResource BoolToVisConverter}}">
<TextBlock Text="T2 (ms) :" Style="{StaticResource OverlayStyle}"/>
</StackPanel>
<TextBlock Grid.Row="25" Grid.Column="1" Text="{Binding T2Time}" Style="{StaticResource OverlayStyle}" Visibility="{Binding HIC, Converter={StaticResource BoolToVisConverter}}"/>
</Grid>
</Grid>
</base:BaseView>

View File

@@ -0,0 +1,269 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Media;
using DTS.Common.Enums.Sensors;
using DTS.Common.Interface;
using DTS.Common.Strings;
// ReSharper disable UnassignedGetOnlyAutoProperty
namespace DTS.Viewer.Graph.Model
{
public class TestDataSeries : Common.Base.BasePropertyChanged, ITestDataSeries
{
private bool _HIC = false;
public bool HIC
{
get => _HIC;
set => SetProperty(ref _HIC, value, "HIC");
}
private string _hicValue;
public string HICValue
{
get => _hicValue;
set => SetProperty(ref _hicValue, value, "HICValue");
}
private string _T1Time;
public string T1Time
{
get => _T1Time;
set => SetProperty(ref _T1Time, value, "T1Time");
}
private string _T2Time;
public string T2Time
{
get => _T2Time;
set => SetProperty(ref _T2Time, value, "T2Time");
}
private string _testGroup = string.Empty;
public string TestGroup
{
get => _testGroup;
set => SetProperty(ref _testGroup, value, "TestGroup");
}
private string _testId = string.Empty;
public string TestId
{
get => _testId;
set => SetProperty(ref _testId, value, "TestId");
}
private string _testSetupName = string.Empty;
public string TestSetupName
{
get => _testSetupName;
set => SetProperty(ref _testSetupName, value, "TestSetupName");
}
private string _channelId = string.Empty;
public string ChannelId
{
get => _channelId;
set => SetProperty(ref _channelId, value, "ChannelId");
}
private double[] _x = new double[0];
public double[] Xvalue
{
get => _x;
set => SetProperty(ref _x, value, "X");
}
private double[] _y = new double[0];
public double[] Yvalue
{
get => _y;
set => SetProperty(ref _y, value, "Y");
}
// 34455: Move from Brush to byte[] to make it thread-safe
private byte[] _graphColorARGB = new byte[] { Colors.Blue.A, Colors.Blue.R, Colors.Blue.G, Colors.Blue.B };
public Brush GraphColor
{
get => new SolidColorBrush(Color.FromArgb(_graphColorARGB[0], _graphColorARGB[1], _graphColorARGB[2], _graphColorARGB[3]));
set
{
var valueColor = ((SolidColorBrush)value).Color;
var colorValues = new byte[] { valueColor.A, valueColor.R, valueColor.G, valueColor.B };
SetProperty(ref _graphColorARGB, colorValues, "GraphColor");
}
}
public bool IsSaved { get; }
public string HardwareChannel { get; set; }
public string GroupName { get; set; }
public string SWAAF { get; set; }
public string Bridge { get; set; }
public string HWAAF { get; set; }
public string SampleRate { get; set; }
public string ISOCode { get; set; }
public string ISOChannelName { get; set; }
public string UserCode { get; set; }
public string UserChannelName { get; set; }
public string ChannelName { get; set; }
public string Description { get; set; }
public string SensorSN { get; set; }
public string SensorSNDisplay
{
get => SensorConstants.IsTestSpecificEmbedded(SensorSN) ? Strings.Table_NA : SensorSN;
}
public string EngineeringUnits { get; set; }
public string Excitation { get; set; }
public string Polarity { get; set; }
private string _minY = Strings.Table_NA;
public string MinY
{
get => _minY;
set => SetProperty(ref _minY, value, "MinY");
}
private string _maxY = Strings.Table_NA;
public string MaxY
{
get => _maxY;
set => SetProperty(ref _maxY, value, "MaxY");
}
private string _avgY = Strings.Table_NA;
public string AvgY
{
get => _avgY;
set => SetProperty(ref _avgY, value, "AvgY");
}
private string _stdDevY;
public string StdDevY
{
get => _stdDevY;
set => SetProperty(ref _stdDevY, value, "StdDevY");
}
private double _peakMagnitude = 0;
/// <summary>
/// holds the peak magnitude of frequencies in signal
/// only valid when FFT true
/// 6402 Implement ability to switch to FFT live in the Review
/// </summary>
public double PeakMagnitude
{
get => _peakMagnitude;
set => SetProperty(ref _peakMagnitude, value, "PeakMagnitude");
}
private double _peakFrequency = 0;
/// <summary>
/// holds the frequency of the highest magnitude in signal
/// only valid when FFT true
/// 6402 Implement ability to switch to FFT live in the Review
/// </summary>
public double PeakFrequency
{
get => _peakFrequency;
set => SetProperty(ref _peakFrequency, value, "PeakFrequency");
}
private double _grms = 0;
/// <summary>
/// holds the root-mean-squared acceleration
/// only calculated in PSD results graphs
/// </summary>
public double GRMS
{
get => _grms;
set => SetProperty(ref _grms, value, "GRMS");
}
private bool _fft = false;
/// <summary>
/// holds whether series is an FFT of signal data
/// 6402 Implement ability to switch to FFT live in the Review
/// </summary>
public bool FFT
{
get => _fft;
set => SetProperty(ref _fft, value, "FFT");
}
private string _T0EUValue = "";
/// <summary>
/// this is the T0 value regardless of units ... it's not really EU but since it's already in use I'm not going to change it
/// </summary>
public string T0EUValue
{
get => _T0EUValue;
set => SetProperty(ref _T0EUValue, value, "T0EUValue");
}
private double CalculateStdDev(double[] values)
{
double ret = 0;
if (!values.Any()) return ret;
//Compute the Average
var avg = values.Average();
//Perform the Sum of (value-avg)_2_2
var sum = values.Sum(d => Math.Pow(d - avg, 2));
//Put it all together
ret = Math.Sqrt(sum / (values.Length - 1));
return ret;
}
private const string STAT_FORMAT = "G5";
/// <summary>
/// sets Ave/StdDev/Min/MaxT0 stats using internal YValues (something like PSD or FFT)
/// </summary>
public void SetStatsFromYValues()
{
SetStatsFromYValues(Yvalue);
}
/// <summary>
/// sets Ave/StdDev/Min/Max/T0 stats using the passed in input range (something like PSD or FFT)
/// </summary>
/// <param name="values"></param>
public void SetStatsFromYValues(double[] values)
{
if (null == values || 0 == values.Length)
{
SetStatsFromYValues(double.NaN, double.NaN, double.NaN, double.NaN, double.NaN);
}
else
{
SetStatsFromYValues(values.Min(), values.Max(), values.Average(), CalculateStdDev(values), double.NaN);
}
}
/// <summary>
/// formats and sets the current unit stats
/// </summary>
/// <param name="min"></param>
/// <param name="max"></param>
/// <param name="ave"></param>
/// <param name="stdDev"></param>
/// <param name="t0Value"></param>
private void SetStatsFromYValues(double min, double max, double ave, double stdDev, double t0Value)
{
StdDevY = double.IsNaN(stdDev) ? Strings.Table_NA : stdDev.ToString(STAT_FORMAT);
AvgY = double.IsNaN(ave) ? Strings.Table_NA : ave.ToString(STAT_FORMAT);
MinY = double.IsNaN(min) ? Strings.Table_NA : min.ToString(STAT_FORMAT);
MaxY = double.IsNaN(max) ? Strings.Table_NA : max.ToString(STAT_FORMAT);
T0EUValue = double.IsNaN(t0Value) ? Strings.Table_NA : t0Value.ToString(STAT_FORMAT);
}
/// <summary>
/// sets stats (ave/min/max) using values from passed in channel where it was already calculated when reading data
/// </summary>
/// <param name="channel"></param>
public void SetStatsFromChannel(ITestChannel channel)
{
SetStatsFromYValues(channel.MinY, channel.MaxY, channel.AveY, channel.StdDevY, channel.T0Value);
}
public string RecordingMode { get; set; }
}
}