scpsection4.cs
来自「ecg tool kit for medical image retrieval」· CS 代码 · 共 681 行 · 第 1/2 页
CS
681 行
/***************************************************************************
Copyright 2004-2005,2008, Thoraxcentrum, Erasmus MC, Rotterdam, The Netherlands
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Written by Maarten JB van Ettinger.
****************************************************************************/
using System;
using System.Runtime.InteropServices;
using Communication.IO.Tools;
using ECGConversion.ECGSignals;
using ECGConversion.ECGGlobalMeasurements;
namespace ECGConversion.SCP
{
/// <summary>
/// Class contains section 4 (QRS locations).
/// </summary>
public class SCPSection4 : SCPSection, ISignal
{
// Defined in SCP.
private static ushort _SectionID = 4;
// Part of the stored Data Structure.
private ushort _MedianDataLength = 0;
private ushort _FirstFiducial = 0;
private ushort _NrQRS = 0xffff;
private SCPQRSSubtraction[] _Subtraction = null;
private SCPQRSProtected[] _Protected = null;
protected override int _Read(byte[] buffer, int offset)
{
int end = offset - Size + Length;
if ((offset + Marshal.SizeOf(_MedianDataLength) + Marshal.SizeOf(_FirstFiducial) + Marshal.SizeOf(_NrQRS)) > end)
{
return 0x1;
}
_MedianDataLength = (ushort) BytesTool.readBytes(buffer, offset, Marshal.SizeOf(_MedianDataLength), true);
offset += Marshal.SizeOf(_MedianDataLength);
_FirstFiducial = (ushort) BytesTool.readBytes(buffer, offset, Marshal.SizeOf(_FirstFiducial), true);
offset += Marshal.SizeOf(_FirstFiducial);
_NrQRS = (ushort) BytesTool.readBytes(buffer, offset, Marshal.SizeOf(_NrQRS), true);
offset += Marshal.SizeOf(_NrQRS);
if ((offset + (_NrQRS * Marshal.SizeOf(typeof(SCPQRSSubtraction)))) > end)
{
return 0x2;
}
_Subtraction = new SCPQRSSubtraction[_NrQRS];
for (int loper=0;loper < _NrQRS;loper++)
{
_Subtraction[loper] = new SCPQRSSubtraction();
int err = _Subtraction[loper].Read(buffer, offset);
if (err != 0)
{
return err << (2 + loper);
}
offset += Marshal.SizeOf(_Subtraction[loper]);
}
if ((offset + (_NrQRS * Marshal.SizeOf(typeof(SCPQRSProtected)))) > end)
{
return 0x0;
}
_Protected = new SCPQRSProtected[_NrQRS];
for (int loper=0;loper < _NrQRS;loper++)
{
_Protected[loper] = new SCPQRSProtected();
int err = _Protected[loper].Read(buffer, offset);
if (err != 0)
{
return err << (2 + loper);
}
offset += Marshal.SizeOf(_Protected[loper]);
}
return 0x0;
}
protected override int _Write(byte[] buffer, int offset)
{
BytesTool.writeBytes(_MedianDataLength, buffer, offset, Marshal.SizeOf(_MedianDataLength), true);
offset += Marshal.SizeOf(_MedianDataLength);
BytesTool.writeBytes(_FirstFiducial, buffer, offset, Marshal.SizeOf(_FirstFiducial), true);
offset += Marshal.SizeOf(_FirstFiducial);
BytesTool.writeBytes(_NrQRS, buffer, offset, Marshal.SizeOf(_NrQRS), true);
offset += Marshal.SizeOf(_NrQRS);
for (int loper=0;loper < _NrQRS;loper++)
{
int err = _Subtraction[loper].Write(buffer, offset);
if (err != 0)
{
return err << loper;
}
offset += Marshal.SizeOf(_Subtraction[loper]);
}
if (_Protected != null)
{
for (int loper=0;loper < _NrQRS;loper++)
{
int err = _Protected[loper].Write(buffer, offset);
if (err != 0)
{
return err << loper;
}
offset += Marshal.SizeOf(_Protected[loper]);
}
}
return 0x0;
}
protected override void _Empty()
{
_MedianDataLength = 0;
_FirstFiducial = 0;
_NrQRS = 0xffff;
_Subtraction = null;
_Protected = null;
}
protected override int _getLength()
{
if (Works())
{
int sum = (Marshal.SizeOf(_MedianDataLength) + Marshal.SizeOf(_FirstFiducial) + Marshal.SizeOf(_NrQRS));
sum += (_NrQRS * Marshal.SizeOf(typeof(SCPQRSSubtraction)));
if (_Protected != null)
{
sum += (_NrQRS * Marshal.SizeOf(typeof(SCPQRSProtected)));
}
return ((sum % 2) == 0 ? sum : sum + 1);
}
return 0;
}
public override ushort getSectionID()
{
return _SectionID;
}
public override bool Works()
{
if ((_Subtraction != null)
&& (_Protected != null)
&& (_NrQRS == _Subtraction.Length)
&& (_NrQRS == _Protected.Length)
|| (_NrQRS == 0))
{
if ((_Protected != null)
&& (_Protected.Length != _NrQRS))
{
return false;
}
for (int loper=0;loper < _NrQRS;loper++)
{
if ((_Subtraction[loper] == null)
|| ((_Protected != null)
&& (_Protected[loper] == null)))
{
return false;
}
}
return true;
}
return false;
}
/// <summary>
/// Function to get length of median.
/// </summary>
/// <returns>length of median data.</returns>
public ushort getMedianLength()
{
if (Works())
{
return _MedianDataLength;
}
return 0;
}
/// <summary>
/// Function to add median data to residual data.
/// </summary>
/// <remarks>both signals must have the same sample rate and AVM</remarks>
/// <param name="definition">Data structure containing information about length of residual data.</param>
/// <param name="residual">2D array containing residual data for each lead. On succes will contain rhythm data.</param>
/// <param name="median">2D array containing median data for each lead.</param>
/// <returns>error:
/// 0x001) given data makes no sense.
/// 0x002) Fault in Lead nr 0.
/// 0x004) Fault in Lead nr 1.
/// 0x008) Fault in Lead nr 2.
/// 0x010) Fault in Lead nr 3.
/// 0x020) Fault in Lead nr 4.
/// 0x040) Fault in Lead nr 5.
/// 0x080) Fault in Lead nr 6.
/// 0x100) Fault in Lead nr 7.
/// ...</returns>
public int AddMedians(SCPSection3 definition, short[][] residual, short[][] median)
{
// Check if given data makes sense
if (Works()
&& (definition != null)
&& (residual != null)
&& (median != null)
&& (definition.Works())
&& (median.Length == definition.getNrLeads())
&& (residual.Length == median.Length))
{
int err = 0;
for (int qrsnr=0;qrsnr < _NrQRS;qrsnr++)
{
if ((_Subtraction[qrsnr].Type != 0))
continue;
for (int channel=0;channel < median.Length;channel++)
{
if ((residual[channel] == null)
|| (median[channel] == null)
|| (residual[channel].Length < definition.getLeadLength(channel)))
{
err |= (0x2 << channel);
continue;
}
int loperResidual = _Subtraction[qrsnr].Start - definition.getLeadStart(channel);
int loperMedian = (_FirstFiducial - _Subtraction[qrsnr].Fiducial + _Subtraction[qrsnr].Start - 1);
int endResidual = _Subtraction[qrsnr].End - definition.getLeadStart(channel);
if ((loperResidual >= 0)
&& (loperMedian >= 0))
{
while ((loperResidual <= endResidual)
&& (loperMedian < median[channel].Length))
{
residual[channel][loperResidual++] += median[channel][loperMedian++];
}
}
}
}
return err;
}
return -1;
}
/// <summary>
/// Function to subtract median data to residual data.
/// </summary>
/// <remarks>both signals must have the same sample rate and AVM</remarks>
/// <param name="definition">Data structure containing information about length of rhythm data.</param>
/// <param name="rhythm">2D array containing rhythm data for each lead. On succes will contain residual data.</param>
/// <param name="median">2D array containing median data for each lead.</param>
/// <returns>error:
/// 0x001) given data makes no sense.
/// 0x002) Fault in Lead nr 0.
/// 0x004) Fault in Lead nr 1.
/// 0x008) Fault in Lead nr 2.
/// 0x010) Fault in Lead nr 3.
/// 0x020) Fault in Lead nr 4.
/// 0x040) Fault in Lead nr 5.
/// 0x080) Fault in Lead nr 6.
/// 0x100) Fault in Lead nr 7.
/// ...</returns>
public int SubtractMedians(SCPSection3 definition, short[][] rhythm, short[][] median)
{
// Check if given data makes sense
if (Works()
&& (definition != null)
& (rhythm != null)
&& (median != null)
&& (definition.Works())
&& (median.Length == definition.getNrLeads())
&& (rhythm.Length == median.Length))
{
int err = 0;
for (int qrsnr=0;qrsnr < _NrQRS;qrsnr++)
{
if ((_Subtraction[qrsnr].Type != 0))
continue;
for (int channel=0;channel < median.Length;channel++)
{
if ((rhythm[channel] == null)
|| (median[channel] == null)
|| (rhythm[channel].Length < definition.getLeadLength(channel)))
{
err |= (0x2 << channel);
continue;
}
int loperResidual = _Subtraction[qrsnr].Start - definition.getLeadStart(channel);
int loperMedian = (_FirstFiducial - _Subtraction[qrsnr].Fiducial + _Subtraction[qrsnr].Start - 1);
int endResidual = _Subtraction[qrsnr].End - definition.getLeadStart(channel);
if ((loperResidual >= 0)
&& (loperMedian >= 0))
{
while ((loperResidual <= endResidual)
&& (loperMedian < median[channel].Length))
{
rhythm[channel][loperResidual++] -= median[channel][loperMedian++];
}
}
}
}
return err;
}
return -1;
}
/// <summary>
/// Function to get nr of protected zones.
/// </summary>
/// <returns>nr of protected zones</returns>
public int getNrProtectedZones()
{
return (_Protected != null ? _Protected.Length : 0);
}
/// <summary>
/// Function to get start of protected zone.
/// </summary>
/// <param name="nr">nr of protected zone</param>
/// <returns>start sample nr of protected zone</returns>
public int getProtectedStart(int nr)
{
if ((_Protected != null)
&& (nr >= 0)
&& (nr < _Protected.Length))
{
return _Protected[nr].Start;
}
return -1;
}
/// <summary>
/// Function to get end of protected zone.
/// </summary>
/// <param name="nr">nr of protected zone</param>
/// <returns>end sample nr of protected zone</returns>
public int getProtectedEnd(int nr)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?