/// <summary> /// Возвращает время от получения первого отсчета в данном канале /// до создания данного маркера /// </summary> /// <param name="markerId"></param> /// <param name="channel"></param> /// <returns></returns> public static TimeSpan GetChannelTimeForMarker( this PatientPhysioData _this, long markerId, ChannelData channel) { Marker marker = _this.GetMarkerByIdOrDefault(markerId); System.Diagnostics.Debug.Assert(marker != null); ChannelMark cm = GetChannelMarkByChannelName(marker.ChannelMarks, channel.ChannelId); // Длина канала в микросекундах double channelDataMicroseconds = ((double)channel.Data.Length) / channel.BitsPerSample * OneM; // Положение метки относительно начала данных канала в микросекундах double channelMarkerMicroseconds = ((double)cm.Count) / channel.BitsPerSample * OneM + (double)cm.Offset; if (channelMarkerMicroseconds < 0) { System.Diagnostics.Debug.Assert(false); // такая ситуация может возникнуть в двух случаях // 1. когда метка поставлена в начале отсчета временной шкалы измерения, // а за время выполнения цикла создания меток каналов в одном из каналов // появились новые данные, при этом смещение метки канала будет отрицательным, // а абсолютное значение смещения может быть больше чем (cm.Count / channel.BitsPerSample * 1000000.0) // 2. когда метка ставится на канал, в котором еще нет данных channelMarkerMicroseconds = 0; } // исправить //return new System.TimeSpan( (marker.TimestampUsec - cm.Offset) * 10 ); // на return(new TimeSpan((long)Math.Floor(Math.Min(channelMarkerMicroseconds, channelDataMicroseconds)) * 10)); }
/// <summary> /// защита от неправильного использования отсутствует, /// поэтому нельзя делать эту функцию public /// </summary> public static ChannelData CutChannelDataFromLeftToRight( this PatientPhysioData _this, ChannelData channel_data, Marker left_marker, Marker right_marker) { System.Diagnostics.Debug.Assert(channel_data != null); lock (channel_data) { int left_index = 0; int right_index = channel_data.Data.Length - 1; if (left_marker != null) { ChannelMark lcm = GetChannelMarkByChannelName(left_marker.ChannelMarks, channel_data.ChannelId); System.Diagnostics.Debug.Assert(lcm != null); double offsetInSeconds = ((double)lcm.Offset) / OneM; long offsetInSamples = (long)Math.Floor(offsetInSeconds * channel_data.SamplingRate); left_index = (int)Math.Max(lcm.Count + offsetInSamples - 1, left_index); } if (right_marker != null) { ChannelMark rcm = GetChannelMarkByChannelName(right_marker.ChannelMarks, channel_data.ChannelId); System.Diagnostics.Debug.Assert(rcm != null); double offsetInSeconds = ((double)rcm.Offset) / OneM; long offsetInSamples = (long)Math.Floor(offsetInSeconds * channel_data.SamplingRate); right_index = (int)Math.Min(rcm.Count + offsetInSamples - 1, right_index); } return(new ChannelData(channel_data, left_index, right_index)); } }
public static ChannelData GetChannelDataFromLeftToRight( this PatientPhysioData _this, ChannelData channelData, long leftMarkerId, long rightMarkerId) { return(_this.GetChannelDataFromLeftToRight(channelData, leftMarkerId, 0, rightMarkerId, 0)); }
public ChannelData(ChannelData src) { BitsPerSample = src.BitsPerSample; ChannelId = src.ChannelId; DeviceTypeName = src.DeviceTypeName; SamplingRate = src.SamplingRate; PhysioSignalType = src.PhysioSignalType; Data = new int[src.Data.Length]; Array.Copy(src.Data, Data, src.Data.Length); Timestamps = new Dictionary <long, long>(src.Timestamps); }
public static long GetChannelDataCountForMarker( this PatientPhysioData _this, ChannelData data, long markerId) { Marker marker = _this.GetMarkerByIdOrDefault(markerId); if (null != marker) { ChannelMark m = GetChannelMarkByChannelName(marker.ChannelMarks, data.ChannelId); if (null != m) { return(m.Count + ((long)(((double)m.Offset) * data.SamplingRate / OneM))); } } return(-1); }
public static ChannelData GetChannelDataFromLeftToRight( this PatientPhysioData _this, ChannelData channelData, long leftMarkerId, long leftMarkerOffset, long rightMarkerId, long rightMarkerOffset) { if (null == channelData) { return(null); } Marker leftMarker = _this.GetMarkerByIdOrDefault(leftMarkerId); Marker rightMarker = _this.GetMarkerByIdOrDefault(rightMarkerId); // Вырезать данные и вернуть их. return(_this.CutChannelDataFromLeftToRight(channelData, leftMarker, rightMarker)); }
/// <summary> /// Смещает метку канала на заданное кол-во микросекунд. /// Возвращает смещение в микросекундах, /// на которое реально была перемещена метка канала. /// </summary> /// <param name="marker">Метка канала</param> /// <param name="offset">Смещение метки в микросекундах</param> /// <param name="channel">Канал данных</param> public static double MoveChannelMarker( this PatientPhysioData _this, ChannelMark marker, long offset, ChannelData channel) { // Частота оцифровки канала double samplingRate = channel.SamplingRate; // Кол-во данных канала double dataCount = channel.Data.Length; // Длина канала в микросекундах double dataMicroseconds = dataCount / samplingRate * OneM; // Положение метки во времени относительно начала данных канала в микросекундах double markerPosition = ((double)marker.Count) / samplingRate * OneM + (double)marker.Offset; // Новое положение метки на канале в микросекундах double newMarkerPosition = markerPosition + (double)offset; if (newMarkerPosition < 0) { newMarkerPosition = 0; } else if (newMarkerPosition > dataMicroseconds) { newMarkerPosition = dataMicroseconds; } // Новое кол-во отсчетов метки marker.Count = (long)Math.Floor(newMarkerPosition * samplingRate / OneM); // Новое смещение метки в микросекундах marker.Offset = (long)Math.Floor(newMarkerPosition - ((double)marker.Count) / samplingRate * OneM); // Новое положение метки на канале с учетом Math.Floor newMarkerPosition = ((double)marker.Count) / samplingRate * OneM + (double)marker.Offset; // Смещение в микросекундах, на которое реально была перемещена метка канала return(newMarkerPosition - markerPosition); }
/// <summary> /// Конструктор копий, позволяющий вырезать фрагмент данных /// </summary> /// <param name="src"></param> /// <param name="leftIndex"></param> /// <param name="rightIndex"></param> public ChannelData(ChannelData src, int leftIndex, int rightIndex) { lock (src) { if (leftIndex > rightIndex) { throw new ArgumentException( $"{nameof(leftIndex)}={leftIndex} must be less than or equal to {nameof(rightIndex)}={rightIndex}"); } BitsPerSample = src.BitsPerSample; ChannelId = src.ChannelId; SamplingRate = src.SamplingRate; DeviceTypeName = src.DeviceTypeName; PhysioSignalType = src.PhysioSignalType; int newCount = rightIndex - leftIndex + 1; Data = new int[newCount]; Array.Copy(src.Data, leftIndex, Data, 0, newCount); // Не добавляем метки времени, не попавшие // между leftIndex и rightIndex включительно Timestamps = new Dictionary <long, long>(); if (src.Timestamps != null) { foreach (long timestamp in src.Timestamps.Keys) { long count = src.Timestamps[timestamp]; if ((leftIndex < count) && (count <= (rightIndex + 1))) { Timestamps[timestamp] = (long)(count - leftIndex); } } } } }
/// <summary> /// Смещает метку канала на заданное кол-во микросекунд. /// Возвращает смещение в микросекундах, /// на которое реально была перемещена метка канала. /// </summary> /// <param name="markerId">Идентификатор метки</param> /// <param name="markerOffset">Смещение метки в микросекундах</param> /// <param name="channel">Канал данных</param> public static double MoveChannelMarker(this PatientPhysioData _this, long markerId, long markerOffset, ChannelData channel) { if (!_this.ContainsMarker(markerId)) { return(0); } var marker = _this.GetMarkerByIdOrDefault(markerId); if (null == marker) { return(0); } var channelMarker = GetChannelMarkByChannelName(marker.ChannelMarks, channel.ChannelId); if (null == channelMarker) { return(0); } return(_this.MoveChannelMarker(channelMarker, markerOffset, channel)); }
public static float[] GetDataAsFloat(this ChannelData _this) { return(_this.Data.Select(sample => (float)sample).ToArray()); }