How do I connect an IObservableList<double[]> to a list of objects with an IObservableList<double> property

58 Views Asked by At

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;
}
0

There are 0 best solutions below