D3绘图仪和文件监视器,干扰

本文关键字:干扰 监视器 文件 绘图仪 D3 | 更新日期: 2023-09-27 18:02:39

我使用文件监视器监视文件输出,然后使用d3(动态数据显示)动态显示结果。这里有更多的细节:

  1. 数据是一系列快速生成的tiff文件(每个文件生成20-25毫秒);
  2. 一旦有文件进来,事件被触发,文件被处理(一些统计计算);
  3. 结果将被发送到d3绘图仪,该绘图仪将在宪章上动态显示结果。

当我关闭d3包机窗口时,文件监视器捕获几乎所有的事件,但这是我的问题:

  • 然而,当我离开d3包机窗口打开时,即使没有任何统计计算,文件监视器掉落许多事件(一些大的差距发生)。

这是我们尝试过的:

  • 增加观察者缓冲区,但是,只要d3宪章窗口打开,它仍然会掉落事件。
  • 使用c++ dll来计算统计数据,但是看起来更慢。

所以我想知道:

  • d3绘图仪和文件监视器是否相互冲突/干扰?
  • 我可以用它们一起来实时绘图吗?
  • 有什么办法可以解决我的问题吗?

欢迎指教。

下面是d3绘图仪的代码,包括构造函数、绘图仪启动器和绘图仪更新:

#region Constructor
public SignalStatsDisplay()
{
    InitializeComponent();
    //   timeDomainPlotter.Legend.Remove();
    _initialChildrenCount = timeDomainPlotter.Children.Count;
    int count = timeDomainPlotter.Children.Count;
    //do not remove the initial children
    if (count > _initialChildrenCount)
    {
        for (int i = count - 1; i >= _initialChildrenCount; i--)
        {
            timeDomainPlotter.Children.RemoveAt(i);
        }
    }
    _nMaxStatsOneChannel = Enum.GetNames(typeof(Window1.ROISignalList)).Length;
    _curveBrush = new Brush[_nMaxStatsOneChannel];
    _statsEnable = new int[_nMaxStatsOneChannel];
    for (int i = 0; i < _nMaxStatsOneChannel; i++)
    {
        _curveBrush[i] = new SolidColorBrush((Color)ColorConverter.ConvertFromString(_colorList[i]));
        _statsEnable[i] = 0;
    }
    _nActiveStatsOneChannel = 0;
}
#endregion Constructor
public void InitiateSignalAnalysisPlot()
{
    _statsName = Enum.GetNames(typeof(Window1.ROISignalList));
    int count = 0;
    _statsEnableIndex = new int[_nActiveStatsOneChannel];
    for (int i = 0; i < _nMaxStatsOneChannel; i++)  // assign color
    {
        if (_statsEnable[i] == 1)
        {
            _statsEnableIndex[count] = i;
            count++;
        }
    }

    if (_nActiveChannel > 0)    // timeDomainPlotter init
    {
        _dataX = new List<double[]>();
        _dataY = new List<double[]>();
        double[] dataXOneCh = new double[_signalLength];
        double[] dataYOneCh = new double[_signalLength];
        dataXOneCh[0] = 0;
        dataYOneCh[0] = 0;
        for (int i = 0; i < _nActiveChannel; i++)
        {
            for (int j = 0; j < _nActiveStatsOneChannel; j++)
            {
                _dataX.Add(dataXOneCh);    // data x-y mapping init
                _dataY.Add(dataYOneCh);
                EnumerableDataSource<double> xOneCh = new EnumerableDataSource<double>(dataXOneCh);
                EnumerableDataSource<double> yOneCh = new EnumerableDataSource<double>(dataYOneCh);
                xOneCh.SetXMapping(xVal => xVal);
                yOneCh.SetXMapping(yVal => yVal);
                CompositeDataSource dsOneCh = new CompositeDataSource(xOneCh, yOneCh);
                LineAndMarker<MarkerPointsGraph> lam = timeDomainPlotter.AddLineGraph(dsOneCh,
                    new Pen(_curveBrush[_statsEnableIndex[j]], 2),
                    new CirclePointMarker { Size = 5, Fill = _curveBrush[_statsEnableIndex[j]] },
                    new PenDescription(_statsName[_statsEnableIndex[j]]));
            }
        }
        Action FitToView = delegate()
        {
            timeDomainPlotter.FitToView();
        };
        this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, FitToView);
    }
    else
    {
        return;
    }
}
public void RedrawSignalAnalysisPlot()
{
    int startIndex = _initialChildrenCount;
    if ((_nActiveStatsOneChannel > 0) && (_dataX != null) && (_dataY != null))
    {
        CompositeDataSource[] dsCh = new CompositeDataSource[_nActiveStatsOneChannel];
        int m, n;
        int index;
        for (int i = 0; i < _nActiveChannel; i++)
        {
            for (int j = 0; j < _nActiveStatsOneChannel; j++)
            {
                index = i * _nActiveStatsOneChannel + j;
                if (_dataX[index].Length == _dataY[index].Length)
                {
                    EnumerableDataSource<double> xOneCh = new EnumerableDataSource<double>(_dataX[index]);
                    xOneCh.SetXMapping(xVal => xVal);
                    EnumerableDataSource<double> yOneCh = new EnumerableDataSource<double>(_dataY[index]);
                    yOneCh.SetYMapping(yVal => yVal);
                    CompositeDataSource ds = new CompositeDataSource(xOneCh, yOneCh);
                    Action UpdateData = delegate()
                    {
                        m = i * 2;
                        n = j * 2;
                        // ((LineGraph)timeDomainPlotter.Children.ElementAt(startIndex + n + m * _nActiveStatsOneChannel)).DataSource = ds;
                        // ((LineGraph)timeDomainPlotter.Children.ElementAt(startIndex + n + m * _nActiveStatsOneChannel)).LinePen
                        //    = new Pen(new SolidColorBrush(_curveBrush[j]), 1);
                        ((MarkerPointsGraph)timeDomainPlotter.Children.ElementAt(startIndex + n + 1 + m * _nActiveStatsOneChannel)).DataSource = ds;
                        //  ((MarkerPointsGraph)timeDomainPlotter.Children.ElementAt(startIndex + n + 1 + m * _nActiveStatsOneChannel)).Marker
                        //      = new CirclePointMarker { Size = 5, Fill = Brushes.Green };
                    };
                    this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, UpdateData);
                }
            }

        }
        /* Action PlotFitToView = delegate()
          {
              timeDomainPlotter.FitToView();
          };
         this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, PlotFitToView);*/
    }
}

下面是文件被监控的方式:其中事件(文件写入)被归档

void tiffWatcher_EventChanged(object sender, WatcherExEventArgs e)
{
    string fileName = ((FileSystemEventArgs)(e.Arguments)).FullPath;
    string fileExt = StringExtension.GetLast(fileName, 4);
    if (!IsFileLocked(fileName))
    {
        Action EventFinished = delegate()
        {
            CreateListViewItem(fileName, "Finished", DateTime.Now.ToString("HH:mm:ss.fff"));
        };
        listView1.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, EventFinished);
        _tiffName.Add( fileName);
        _tiffFilledCount++;    
    }
}

tiff数据处理,以及与d3绘图仪的数据通信:

void tiffTimer_Tick(object sender, EventArgs e)
{
    //throw new NotImplementedException();
    byte[] image = new byte[_signalManager.ImgWidth * _signalManager.ImgHeight];
    if (_tiffFilledCount - _tiffProcessedCount >= 1)
    {

        string fileName = _tiffName[_tiffProcessedCount++];
        char filePre = fileName[49];
        int indexBeigin = fileName.LastIndexOf("_");
        int indexEnd = fileName.LastIndexOf(".");
        _signalIndex = Convert.ToInt32(fileName.Substring(indexBeigin + 1, indexEnd - indexBeigin - 1)) - 1; // 0 based//
        _deltaT = ExtractTiffDeltaT(fileName, "DeltaT=", 1);
        _channelIndex = (int)Enum.Parse(typeof(ChannelList), Convert.ToString(filePre));
        TIFFIImageIO.LoadTIFF(fileName, ref image);
        _signalManager.Image = image;
        for (int i = 0; i < _nActiveStatsOneChannel; i++)
        {
            _signalManager.GetSignal( _signalDisplay.StatsEnableIndex[i], ref _signal);
            UpdateSignal(_channelIndex, i, _tiffProcessedCount-1, _deltaT, _signal);
        }
      // if( _tiffProcessedCount % 5 == 0)
        _signalDisplay.SetData(_XList, _YList, true);
    }
}

我使用定时器。选择每隔50-100毫秒处理一次文件,仍在测试中。

D3绘图仪和文件监视器,干扰

我处理它的方式是设置一个计时器,循环处理计算,显示。到目前为止,它运行良好。当然会有很多事件丢失,但是我们处理的点比较多(几千个),所以几百个来做情节是可以的。下面是代码:

private Timer _tiffTimer;
void Window1_Loaded(object sender, RoutedEventArgs e)
        {
            //throw new NotImplementedException();
            _tiffTimer = new Timer();
            _tiffTimer.Interval = 50;  // change interval to change performance
            _tiffTimer.Tick += new EventHandler(tiffTimer_Tick);
            _tiffTimer.Start();
        }
void tiffTimer_Tick(object sender, EventArgs e)
        {
            //do your stuff here
        }