01-30-2017 10:15 AM
Hello,
In my latest project I'm working with double[] arrays where I apply all kinds of filters to an entire array at once using a 3rd party library. When it's time to plot the data, I don't have the correct X-axis values because I'm not using Point[] arrays (so X-axis is just 0 to N incremented by 1).
What is the "cheapest" way out of this? I mean, I don't want to loop through the entire array (could be 20-30K long each * 32) and create Point objects out of doubles. In MATLAB there's a way to simply assign a separate array to X-axis so I was wondering if there's something like this in NI Lib.
Thanks!
Solved! Go to Solution.
01-30-2017 10:55 AM
For the WPF controls, we do have the ChartCollection<TIndexData,TSampleData>
types for accumulating a history of data, but we do not have an equivalent collection type for plotted data. Assuming the chart collection will not work for your use case, there are two main approaches to displaying your data with custom index values:
IGraphDataCollection
interface.It would be helpful to know what are “the correct X-axis values” you’re looking for, to give you more specific suggestions.
01-30-2017 11:08 AM
Hi Paul,
My Y-axis is Nano Tesla and my X-axis is seconds. Seconds array is calculated by multiplying one of the data array by sample rate. I hope this clarifies it.
Thanks
01-30-2017 01:21 PM
Based on your description, it sounds like you are reading values at a fixed sample rate. In that case, here are simple versions of each of the approaches above:
Custom value presenter for array data:
public class CustomSampleRateFormatter : GeneralValueFormatter {
public double Start { get; set; }
public double Rate { get; set; }
public CustomSampleRateFormatter( ) {
Start = 0.0;
Rate = 1.0;
}
protected override string FormatCore<TData>( TData value, ValuePresenterArgs args ) {
double shiftedValue = Start + Convert.ToDouble( value ) * Rate;
return base.FormatCore<double>( shiftedValue, args );
}
protected override Freezable CreateInstanceCore( ) {
return new CustomSampleRateFormatter( );
}
}
Custom collection for publishing data:
[DataTypeDescriptor( typeof( GraphDataCollectionDescriptor<> ) )]
public class DataCollection<TData> : IGraphDataCollection {
private double start;
private double rate;
private TData[] data;
public DataCollection( ) {
SetData( 0.0, 1.0, new TData[0] );
}
public void SetData( double start, double rate, TData[] data ) {
this.start = start;
this.rate = rate;
this.data = data;
DataChanged( this, new GraphCollectionChangedEventArgs( Count ) );
}
#region IGraphDataCollection Members
private static readonly ReadOnlyCollection<Type> DataTypes = new ReadOnlyCollection<Type>( new[] { typeof( double ), typeof( TData ) } );
public int Count { get { return this.data.Length; } }
public bool? MarkIndexData { get; set; }
public event EventHandler<GraphCollectionChangedEventArgs> DataChanged = delegate { };
public ReadOnlyCollection<Type> GetDataTypes( ) { return DataTypes; }
public BufferCollection GetDataBuffers( Trait decomposeOption ) {
var indexData = SequenceBufferPool.CreateIntervalBuffer( Count, Unit.None, this.start, this.rate );
var sampleData = BufferPool.Default.GetBuffer( this.data, Unit.None );
if( MarkIndexData ?? true )
indexData.Traits.Add( IndexBufferTrait.Instance );
return new BufferCollection(indexData, sampleData);
}
void IGraphDataCollection.LoadDataBuffers( IList<IBuffer> dimensionValues ) { throw new NotSupportedException( ); }
#endregion
}
After testing them out, the custom data collection will probably be the most useful (all parts of the graph will recognize the domain of the incoming data, as opposed to just the displayed value on the scale). This is a bare-bones implementation, so feel free to customize it to better match your use case.
01-30-2017 01:40 PM
Thank you, Paul.
Yes, it's a fixed sample rate.
I will try your suggestion sometime this week.
Thanks!