I want to read data from a file or an analog digital converter (ADC) and convert the data with the help of the dynamicdata library. Suppose I read blocks of 2d matrices of ushort numbers from this file or ADC. In the example below I add a 2d matrix to the FileNode class and that is converted to an IObservableList<double[]> list. Now I want to connect this to the Data property of the SampledSignal class which is of type IObservableList<double>. Does anyone have any idea how I should do this?
public class SampledSignal
{
public SampledSignal(IObservableList<double> data, double sr)
{
Data = data;
Samplerate = sr;
}
public IObservableList<double> Data { get; private set; }
public double Samplerate { get; }
}
public class FileNode : ReactiveObject
{
readonly IObservable<IEnumerable<ushort[]>> _currentDataObsv;
const int _signalCount = 4;
readonly private SampledSignal[] _sampledSignals;
public FileNode()
{
_sampledSignals = Enumerable.Range(0, _signalCount)
.Select(s => new SampledSignal(null, 200)).ToArray();
CurrentData = Enumerable.Empty<ushort[]>();
_currentDataObsv = this.WhenAnyValue(x => x.CurrentData);
IObservableList<double[]> dblArList = _currentDataObsv
.ToObservableChangeSet()
.TransformMany(d => ToEnumerable(d))
.AsObservableList();
// The lines below are just some code to give an idea of what I want
for (int i = 0; i < _signalCount; i++)
{
// maybe here an observablelist should be created?
// IObservableList<double> data = ??
// _sampledSignals[i] = new SampledSignal(data, 200);
}
OutSignals=_sampledSignals;
}
public IEnumerable<double[]> ToEnumerable(ushort[] array)
{
double offset = 0;
double amp = 4;
int len = array.Length;
int cnt = 0;
double[] x = new double[len];
for (int i = 0; i < len; i++)
{
x[i] = Convert.ToDouble(array[i] - short.MaxValue) / ushort.MaxValue * amp + offset;
}
cnt++;
yield return x;
}
[Reactive] public IEnumerable<ushort[]> CurrentData { get; set; }
// maybe this property can also be an IObservableList<SampledSignal> OutSignals
public IEnumerable<SampledSignal> OutSignals { get; private set; }
}
[Fact]
public void Test_SampledData()
{
int signalcount = 20;
IEnumerable<ushort[]> array = Enumerable.Range(0, 4)
.Select(j =>
{
var x = new ushort[signalcount];
for (int i = 0; i < x.Length; i++)
{
x[i] = Convert.ToUInt16(short.MaxValue+(i+j)*4);
}
return x;
});
var filenode = new FileNode();
filenode.CurrentData = array;
// do some testing below
SampledSignal signal = filenode.OutSignals.First();
signal.Should().NotBeNull();
signal.Data.Count.Should().Be(signalcount);
}
I have created a solution that works but I don't like it very much because I have to create a SourceList class in the SampledData class. I was hoping for a solution were I directly could set the IObservable<double> Data property of the SampledData class.
// The SampledSignal class now looks like this.
public class SampledSignal
{
private readonly ISourceList<double> _sourceList = new SourceList<double>();
public SampledSignal(IObservableList<double> data, double sr)
{
Data = _sourceList;
Samplerate = sr;
}
public ISourceList<double> Data { get; private set; }
public double Samplerate { get; }
}
// The FileNode constructor now looks like this
public FileNode()
{
_sampledSignals = Enumerable.Range(0, _signalCount)
.Select(s => new SampledSignal(null, 200)).ToArray();
CurrentData = Enumerable.Empty<ushort[]>();
_currentDataObsv = this.WhenAnyValue(x => x.CurrentData);
IObservableList<double[]> dblArList = _currentDataObsv
.ToObservableChangeSet()
.TransformMany(d => ToEnumerable(d))
.AsObservableList();
dblArList.Connect().ToCollection()
.Subscribe(sigs =>
{
int cnt = 0;
foreach (var sig in sigs)
{
var regdata = _sampledSignals[cnt++];
regdata.Data.Edit(innerlist =>
{
innerlist.Clear();
innerlist.AddRange(sig);
});
}
});
OutSignals=_sampledSignals;
}