Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Saving all annotations in each AnnotationSignal #15

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions EDF/EDFWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,15 +170,24 @@ private void WriteSignals(EDFFile edf)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void WriteAnnotations(int index, List<TAL> annotations, int sampleCountPerRecord)
{
var blockSize = sampleCountPerRecord * 2;

var bytesWritten = 0;
bytesWritten += WriteAnnotationIndex(index);
if (index < annotations.Count)
while (index < annotations.Count)
{
// Ensure that the TAL does not span more than a single Data Record
var bytesToWrite = TALExtensions.GetByteSize( annotations[ index ] );
if( bytesWritten + bytesToWrite > blockSize )
{
break;
}

bytesWritten += WriteAnnotation(annotations[index]);
index += 1;
}

//Fills block size left with 0
var blockSize = sampleCountPerRecord * 2;
#if TRACE_BYTES
Debug.WriteLine($"Total bytes for Annotation index {0} is {bytesWritten}");
#endif
Expand Down
37 changes: 34 additions & 3 deletions EDF/TAL.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
Expand All @@ -12,7 +13,7 @@ namespace EDFCSharp
/// </summary>
public class TAL
{
private const string StringDoubleFormat = "0.###";
private const string StringDoubleFormat = "0.########";
/// <summary>
/// Character used for separating onset and duration
/// </summary>
Expand Down Expand Up @@ -89,26 +90,56 @@ public override int GetHashCode()
public static class TALExtensions
{
/// <summary>
/// Returns a byte array witch represent a TAL format according to
/// Returns a byte array which represent a TAL format according to
/// https://www.edfplus.info/specs/edfplus.html#annotationssignal section 2.2.2.
/// </summary>
/// <param name="tal"></param>
/// <returns></returns>
public static byte[] GetBytes(TAL tal)
{
List<byte> result = new List<byte>();
var size = GetByteSize( tal );
List<byte> result = new List<byte>( size );

result.AddRange(Encoding.ASCII.GetBytes(tal.StartSecondsString));

if (tal.DurationSecondsString != null)
{
result.Add(TAL.byte_21); //15 in HEX
result.AddRange(Encoding.ASCII.GetBytes(tal.DurationSecondsString));
}

result.Add(TAL.byte_20);
result.AddRange(Encoding.ASCII.GetBytes(tal.AnnotationDescription));
result.Add(TAL.byte_20);
result.Add(TAL.byte_0);

Debug.Assert( result.Count == size, $"Mismatch between {nameof(GetByteSize)}() and actual number of bytes written" );

return result.ToArray();
}

/// <summary>
/// Returns the number of bytes needed to write a TAL to a Data Record. Used to ensure that
/// a TAL does not exceed the end of a Data Record.
/// </summary>
/// <param name="tal"></param>
/// <returns></returns>
public static int GetByteSize( TAL tal )
{
int size = tal.StartSecondsString.Length;

if( tal.DurationSecondsString != null )
{
size += 1; // TAL.byte_21, 15 HEX
size += tal.DurationSecondsString.Length;
}

size += 1; // TAL.byte_20
size += tal.AnnotationDescription.Length;
size += 2; // TAL.byte20, TAL.byte_0

return size;
}
public static List<TAL> BytesToTALs(byte[] raw)
{
List<TAL> result = new List<TAL>();
Expand Down
20 changes: 17 additions & 3 deletions Tests/UnitTest1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,24 @@ public void ReadAndSaveAnnotationOnlyFile()

string file2 = "test2.edf";
edf.Save(file2);

var edf2 = new EDFFile(file2);
Assert.IsTrue(edf2.Header.Equals(edf.Header));
Assert.IsTrue(edf2.Signals.SequenceEqual(edf.Signals));
Assert.IsTrue(edf2.AnnotationSignals.SequenceEqual(edf.AnnotationSignals));
Assert.IsTrue( edf2.Header.Equals( edf.Header ), "Saved Header does not match original" );
Assert.IsTrue( edf2.Signals.SequenceEqual( edf.Signals ), "Saved Signals do not match original" );
Assert.AreEqual( edf.AnnotationSignals.Count, edf2.AnnotationSignals.Count, "Saved file contains a different number of Annotation Signals than original." );

for( int i = 0; i < edf.AnnotationSignals.Count; i++ )
{
var original = edf.AnnotationSignals[ i ];
var compare = edf2.AnnotationSignals[ i ];

Assert.IsTrue( original.SamplesCount == compare.SamplesCount, "Annotation signals contain a differing number of samples" );

for( int j = 0; j < original.SamplesCount; j++ )
{
Assert.AreEqual( original.Samples[ j ].ToString().Trim(), compare.Samples[ j ].ToString().Trim(), false, "Stored Annotation samples differ" );
}
}
}
[TestMethod]
public void ReadAnnotationAndSignalsFile()
Expand Down