├── codecov.yml
├── .github
├── FUNDING.yml
└── workflows
│ ├── Version-Increment.yml
│ ├── codacy-analysis.yml
│ ├── codeql-analysis.yml
│ └── dotnet-core-desktop.yml
├── hdf5Wrapper.ico
├── hdf5Wrapper.png
├── Assets
├── HDF_logo.svg
├── HDFlogo128.png
├── hdf5Wrapper.jpg
├── hdf5Wrapper.png
├── hdf5Wrapper.xcf
├── hdf5FlatStructure.jpg
└── nuget.svg
├── misc
└── HDF.Pinvoke.snk
├── HDF5-CSharp
├── hdf5Wrapper.ico
├── Hdf5DotNetTools.snk
├── Knf.Utils.Hdf5.snk
├── DataTypes
│ ├── Hdf5Exception.cs
│ ├── Enums.cs
│ ├── FileClosedArgs.cs
│ ├── Hdf5Patient.cs
│ ├── Hdf5Events.cs
│ ├── Hdf5Channel.cs
│ ├── Hdf5Channels.cs
│ ├── Hdf5Recording.cs
│ ├── Hdf5Event.cs
│ ├── Attributes.cs
│ └── DataTypes.cs
├── Interfaces
│ ├── IHdf5AcquisitionFile.cs
│ └── IHdf5ReaderWriter.cs
├── Hdf5Errors.cs
├── Hdf5AttributeRW.cs
├── Hdf5AcquisitionFile.cs
├── Hdf5Conversions.cs
├── Hdf5Settings.cs
├── Hdf5Groups.cs
├── DataProducerConsumer.cs
├── Properties
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── HDF5-CSharp.csproj
└── Hdf5AcquisitionWriter.cs
├── HDF5-CSharp.UnitTests
├── testFile.H5
├── FileStructure.h5
├── files
│ └── testCompounds_WData2_WData3.H5
├── FilesUnitTests.cs
├── HDF5-CSharp.UnitTests.csproj
├── H5ETest.cs
├── Hdf5GroupTests.cs
├── Hdf5ObjectTests.cs
├── Hdf5StringsTests.cs
└── TestUtilities.cs
├── HDF5-CSharp.Viewer
├── App.config
├── Properties
│ ├── Settings.settings
│ ├── Settings.Designer.cs
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── Form1.cs
├── Program.cs
├── HDF5FileLoader.cs
├── Form1.Designer.cs
├── HDF5-CSharp.Viewer.csproj
├── HDF5FileLoader.Designer.cs
├── Form1.resx
└── HDF5FileLoader.resx
├── HDF5-CSharp.Example
├── DataTypes
│ ├── Enums.cs
│ ├── Constants.cs
│ ├── InjectionGroup.cs
│ ├── ElectrodeAmpCalcConfig.cs
│ ├── AcquisitionInformation.cs
│ ├── ProcedureInfo.cs
│ ├── UserEventRecord.cs
│ ├── CalibrationsSystemInformation.cs
│ ├── RPositionEvent.cs
│ ├── Hdf5Events.cs
│ ├── ECGFrame.cs
│ ├── BlockingCollectionQueue.cs
│ ├── CalibrationGroup.cs
│ ├── TagsGroup.cs
│ ├── ElectrodeFrame.cs
│ ├── Hdf5BaseFile.cs
│ ├── UserEventsGroup.cs
│ ├── AssemblyInformationRecord.cs
│ ├── ProcedureInformation.cs
│ ├── EventGroup.cs
│ ├── Patient.cs
│ ├── SystemEventGroup.cs
│ ├── ECGData.cs
│ ├── systemEvent.cs
│ ├── RPositionGroup.cs
│ ├── PatientsContainer.cs
│ ├── ECGCycleDescription.cs
│ ├── SystemInformation.cs
│ ├── EITEntry.cs
│ └── RPositions.cs
├── HDF5-CSharp.Example.csproj
├── GeneralUtils.cs
└── KamaAcquisitionReadOnlyFile.cs
├── .gitattributes
├── HDF5-CSharp.Example.UnitTest
├── AcquisitionScanProtocol.json
└── HDF5-CSharp.Example.UnitTest.csproj
├── azure-pipelines-1.yml
├── license.md
├── azure-pipelines.yml
├── HDF5-CSharp.sln
└── .gitignore
/codecov.yml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | open_collective: lior-banai
2 |
--------------------------------------------------------------------------------
/hdf5Wrapper.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SciSharp/HDF5-CSharp/HEAD/hdf5Wrapper.ico
--------------------------------------------------------------------------------
/hdf5Wrapper.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SciSharp/HDF5-CSharp/HEAD/hdf5Wrapper.png
--------------------------------------------------------------------------------
/Assets/HDF_logo.svg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SciSharp/HDF5-CSharp/HEAD/Assets/HDF_logo.svg
--------------------------------------------------------------------------------
/Assets/HDFlogo128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SciSharp/HDF5-CSharp/HEAD/Assets/HDFlogo128.png
--------------------------------------------------------------------------------
/misc/HDF.Pinvoke.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SciSharp/HDF5-CSharp/HEAD/misc/HDF.Pinvoke.snk
--------------------------------------------------------------------------------
/Assets/hdf5Wrapper.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SciSharp/HDF5-CSharp/HEAD/Assets/hdf5Wrapper.jpg
--------------------------------------------------------------------------------
/Assets/hdf5Wrapper.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SciSharp/HDF5-CSharp/HEAD/Assets/hdf5Wrapper.png
--------------------------------------------------------------------------------
/Assets/hdf5Wrapper.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SciSharp/HDF5-CSharp/HEAD/Assets/hdf5Wrapper.xcf
--------------------------------------------------------------------------------
/Assets/hdf5FlatStructure.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SciSharp/HDF5-CSharp/HEAD/Assets/hdf5FlatStructure.jpg
--------------------------------------------------------------------------------
/HDF5-CSharp/hdf5Wrapper.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SciSharp/HDF5-CSharp/HEAD/HDF5-CSharp/hdf5Wrapper.ico
--------------------------------------------------------------------------------
/HDF5-CSharp/Hdf5DotNetTools.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SciSharp/HDF5-CSharp/HEAD/HDF5-CSharp/Hdf5DotNetTools.snk
--------------------------------------------------------------------------------
/HDF5-CSharp/Knf.Utils.Hdf5.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SciSharp/HDF5-CSharp/HEAD/HDF5-CSharp/Knf.Utils.Hdf5.snk
--------------------------------------------------------------------------------
/HDF5-CSharp.UnitTests/testFile.H5:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SciSharp/HDF5-CSharp/HEAD/HDF5-CSharp.UnitTests/testFile.H5
--------------------------------------------------------------------------------
/HDF5-CSharp.UnitTests/FileStructure.h5:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SciSharp/HDF5-CSharp/HEAD/HDF5-CSharp.UnitTests/FileStructure.h5
--------------------------------------------------------------------------------
/HDF5-CSharp.UnitTests/files/testCompounds_WData2_WData3.H5:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SciSharp/HDF5-CSharp/HEAD/HDF5-CSharp.UnitTests/files/testCompounds_WData2_WData3.H5
--------------------------------------------------------------------------------
/HDF5-CSharp.Viewer/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/HDF5-CSharp/DataTypes/Hdf5Exception.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace HDF5CSharp.DataTypes
4 | {
5 | public class Hdf5Exception : Exception
6 | {
7 |
8 | public Hdf5Exception(string message) : base(message)
9 | {
10 |
11 | }
12 |
13 |
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/Enums.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace HDF5CSharp.Example.DataTypes
6 | {
7 | public enum AcquisitionInterface
8 | {
9 | Kalpa,
10 | Kx,
11 | Simulator
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Viewer/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/HDF5-CSharp/DataTypes/Enums.cs:
--------------------------------------------------------------------------------
1 | namespace HDF5CSharp.DataTypes
2 | {
3 | public enum Hdf5Save
4 | {
5 | Save,
6 | DoNotSave
7 | }
8 |
9 | public enum Hdf5LogLevel
10 | {
11 | Debug,
12 | Info,
13 | Warning,
14 | Error,
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/HDF5-CSharp/DataTypes/FileClosedArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace HDF5CSharp.DataTypes
4 | {
5 | public class FileClosedArgs : EventArgs
6 | {
7 | public string ClosedFile { get; }
8 | public bool CancelRequested { get; set; }
9 |
10 | public FileClosedArgs(string fileName)
11 | {
12 | ClosedFile = fileName;
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/Constants.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace HDF5CSharp.Example.DataTypes
6 | {
7 | public static class Constants
8 | {
9 | public static string SystemInformationGroupName = "system_information";
10 | public static string EventGroupName = "events";
11 | public static string TagGroupName = "tags";
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/InjectionGroup.cs:
--------------------------------------------------------------------------------
1 | using HDF5CSharp.DataTypes;
2 | using Microsoft.Extensions.Logging;
3 |
4 | namespace HDF5CSharp.Example.DataTypes
5 | {
6 | [Hdf5GroupName("injection")]
7 | public class InjectionGroup : Hdf5BaseFile
8 | {
9 | public InjectionGroup(in long fileId, in long groupRoot, ILogger logger) : base(fileId, groupRoot, "injection", logger)
10 | {
11 |
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/HDF5-CSharp/Interfaces/IHdf5AcquisitionFile.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using HDF5CSharp.DataTypes;
3 |
4 | namespace HDF5CSharp.Interfaces
5 | {
6 | public interface IHdf5AcquisitionFile
7 | {
8 | Hdf5Patient Patient { get; set; }
9 | Hdf5Recording Recording { get; set; }
10 | Hdf5Channel[] Channels { get; set; }
11 | List EventList { get; }
12 | Hdf5Events Events { get; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/ElectrodeAmpCalcConfig.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace HDF5CSharp.Example.DataTypes
6 | {
7 | public class ElectrodeAmpCalcConfig
8 | {
9 | public double BF_Limit { get; set; }
10 | public double CF_Limit { get; set; }
11 | public double CurrentAt_0_4_BF { get; set; }
12 | public double CurrentAt_0_4_CF { get; set; }
13 | }
14 |
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Viewer/Form1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace Hdf5DotnetWrapper.Viewer
12 | {
13 | public partial class Form1 : Form
14 | {
15 | public Form1()
16 | {
17 | InitializeComponent();
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.github/workflows/Version-Increment.yml:
--------------------------------------------------------------------------------
1 | name: Version Increment
2 | on:
3 | workflow_dispatch:
4 | inputs:
5 | logLevel:
6 | description: 'Log level'
7 | required: true
8 | default: 'warning'
9 | tags:
10 | description: 'Test scenario tags'
11 |
12 | jobs:
13 | build:
14 | runs-on: windows-latest
15 | steps:
16 | - run: |
17 | echo "Log level: ${{ github.event.inputs.logLevel }}"
18 | echo "Tags: ${{ github.event.inputs.tags }}"
19 |
--------------------------------------------------------------------------------
/HDF5-CSharp/DataTypes/Hdf5Patient.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace HDF5CSharp.DataTypes
4 | {
5 | [Hdf5GroupName("Patient")]
6 | public class Hdf5Patient
7 | {
8 | public string Name = "";
9 | public string Id = "";
10 | public int RecId = -1;
11 | public string Gender = "";
12 | public DateTime BirthDate = DateTime.Now;
13 | public double Height = double.NaN;
14 | public double Weight = double.NaN;
15 | public DateTime EditData = DateTime.Now;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/HDF5-CSharp/DataTypes/Hdf5Events.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace HDF5CSharp.DataTypes
4 | {
5 | [Hdf5GroupName("Events")]
6 | public struct Hdf5Events
7 | {
8 | public string[] Events { get; set; }
9 | public DateTime[] Times { get; set; }
10 | public TimeSpan[] Durations { get; set; }
11 | public Hdf5Events(int length)
12 | {
13 | Events = new string[length];
14 | Times = new DateTime[length];
15 | Durations = new TimeSpan[length];
16 | }
17 |
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/HDF5-CSharp/DataTypes/Hdf5Channel.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | namespace HDF5CSharp.DataTypes
4 | {
5 | [Hdf5GroupName("Channel")]
6 | [StructLayout(LayoutKind.Sequential)]
7 | public struct Hdf5Channel
8 | {
9 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
10 | public string Label;
11 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5)]
12 | public string Dimension;
13 | public double Amplification;
14 | public double Offset;
15 | public double SamplingRate;
16 | public ulong NrOfSamples;
17 |
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Viewer/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using System.Windows.Forms;
6 |
7 | namespace Hdf5DotnetWrapper.Viewer
8 | {
9 | static class Program
10 | {
11 | ///
12 | /// The main entry point for the application.
13 | ///
14 | [STAThread]
15 | static void Main()
16 | {
17 | Application.EnableVisualStyles();
18 | Application.SetCompatibleTextRenderingDefault(false);
19 | Application.Run(new Form1());
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/HDF5-CSharp/Interfaces/IHdf5ReaderWriter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace HDF5CSharp.Interfaces
5 | {
6 | public interface IHdf5ReaderWriter
7 | {
8 | (int success, long CreatedgroupId) WriteFromArray(long groupId, string name, Array dset);
9 | (bool success, Array result) ReadToArray(long groupId, string name, string alternativeName);
10 | (int success, long CreatedgroupId) WriteStrings(long groupId, string name, IEnumerable collection, string datasetName = null);
11 | (bool success, IEnumerable) ReadStrings(long groupId, string name, string alternativeName);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example.UnitTest/AcquisitionScanProtocol.json:
--------------------------------------------------------------------------------
1 | {
2 | "ElectrodeParams": {
3 | "NumOfChannels": 64,
4 | "ActiveChannels": 32,
5 | "DefaultAmplitude": 0.4000000059604645,
6 | "DefaultAmplitudeCF": 0.4000000059604645,
7 | "DefaultAmplitudeBF": 0.4000000059604645,
8 | "GroundChannel": "B6",
9 | "UseBodySurfacePadCalibration": false
10 | },
11 | "BodySensorDescription": {
12 | "Channels": [ "A1", "A2", "A3", "A4", "A5", "A6", "B6" ],
13 | "Amplitudes": [ -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 0.001 ],
14 | "Frequencies": [ 15200.0, 15200.0, 16800.0, 16800.0, 18400.0, 18400.0, 20000.0 ],
15 | "Phases": [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ]
16 | }
17 |
18 | }
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/AcquisitionInformation.cs:
--------------------------------------------------------------------------------
1 | using HDF5CSharp.DataTypes;
2 | using Microsoft.Extensions.Logging;
3 |
4 | namespace HDF5CSharp.Example.DataTypes
5 | {
6 | [Hdf5GroupName("acquisition_information")]
7 | public class AcquisitionInformation : Hdf5BaseFile
8 | {
9 | private string Protocol { get; set; }
10 |
11 | public AcquisitionInformation(AcquisitionProtocolParameters acquisitionProtocol, long fileId, long groupRoot, ILogger logger) : base(fileId, groupRoot, "acquisition_information", logger)
12 | {
13 | Protocol = acquisitionProtocol.AsJson();
14 | }
15 |
16 | public AcquisitionInformation()
17 | {
18 |
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/HDF5-CSharp/Hdf5Errors.cs:
--------------------------------------------------------------------------------
1 | using HDF.PInvoke;
2 | using System;
3 |
4 | namespace HDF5CSharp
5 | {
6 | public static class Hdf5Errors
7 | {
8 | internal static int ErrorDelegateMethod(long estack, IntPtr client_data)
9 | {
10 | H5E.walk(estack, H5E.direction_t.H5E_WALK_DOWNWARD, WalkDelegateMethod, IntPtr.Zero);
11 | return 0;
12 | }
13 |
14 | internal static int WalkDelegateMethod(uint n, ref H5E.error_t err_desc, IntPtr client_data)
15 | {
16 | string msg =
17 | $"{err_desc.desc}. (function: {err_desc.func_name}. Line:{err_desc.line}. File: {err_desc.file_name})";
18 | Hdf5Utils.LogError?.Invoke(msg);
19 | return 0;
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/HDF5-CSharp.Example.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 | HDF5CSharp.Example
6 | HDF5CSharp.Example
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/HDF5-CSharp/DataTypes/Hdf5Channels.cs:
--------------------------------------------------------------------------------
1 | namespace HDF5CSharp.DataTypes
2 | {
3 |
4 | [Hdf5GroupName("Channels")]
5 | public class Hdf5Channels
6 | {
7 | public Hdf5Channels(int length)
8 | {
9 | Labels = new string[length];
10 | Dimensions = new string[length];
11 | Amplifications = new double[length];
12 | Offsets = new double[length];
13 | SamplingRates = new double[length];
14 | NrOfSamples = new int[length];
15 | }
16 | public string[] Labels { get; set; }
17 | public string[] Dimensions { get; set; }
18 | public double[] Amplifications { get; set; }
19 | public double[] Offsets { get; set; }
20 | public double[] SamplingRates { get; set; }
21 | public int[] NrOfSamples { get; set; }
22 |
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Assets/nuget.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Viewer/HDF5FileLoader.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 | using HDF5CSharp.DataTypes;
4 |
5 | namespace Hdf5DotnetWrapper.Viewer
6 | {
7 | public partial class HDF5FileLoader : UserControl
8 | {
9 | public HDF5FileLoader()
10 | {
11 | InitializeComponent();
12 | }
13 |
14 | private void btnHDF5Browse_Click(object sender, EventArgs e)
15 | {
16 | OpenFileDialog of = new OpenFileDialog
17 | {
18 | Multiselect = false,
19 | Filter = "Hdf5 files (*.h5)|*.h5",
20 | };
21 | if (of.ShowDialog() == DialogResult.OK)
22 | {
23 | txtbHDF5.Text = of.FileName;
24 | }
25 | }
26 |
27 | private void btnHDF5ReadFile_Click(object sender, EventArgs e)
28 | {
29 | H5File Hdf5File = new H5File();
30 | Hdf5File.ReadFileStructure(txtbHDF5.Text);
31 |
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/azure-pipelines-1.yml:
--------------------------------------------------------------------------------
1 | # ASP.NET
2 | # Build and test ASP.NET projects.
3 | # Add steps that publish symbols, save build artifacts, deploy, and more:
4 | # https://docs.microsoft.com/azure/devops/pipelines/apps/aspnet/build-aspnet-4
5 |
6 | trigger:
7 | - master
8 |
9 | pool:
10 | vmImage: 'windows-latest'
11 |
12 | variables:
13 | solution: '**/*.sln'
14 | buildPlatform: 'Any CPU'
15 | buildConfiguration: 'Release'
16 |
17 | steps:
18 | - task: NuGetToolInstaller@1
19 |
20 | - task: NuGetCommand@2
21 | inputs:
22 | restoreSolution: '$(solution)'
23 |
24 | - task: VSBuild@1
25 | inputs:
26 | solution: '$(solution)'
27 | msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactStagingDirectory)"'
28 | platform: '$(buildPlatform)'
29 | configuration: '$(buildConfiguration)'
30 |
31 | - task: VSTest@2
32 | inputs:
33 | platform: '$(buildPlatform)'
34 | configuration: '$(buildConfiguration)'
35 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/ProcedureInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace HDF5CSharp.Example.DataTypes
4 | {
5 | //
6 | /// Patient Information class
7 | ///
8 | public class PatientInfo
9 | {
10 | public string PatientFirstName { get; set; }
11 |
12 | public string PatientFamilyName { get; set; }
13 |
14 |
15 | }
16 | ///
17 | /// Exam information
18 | ///
19 | public class ProcedureInfo
20 | {
21 | ///
22 | /// Patient Info
23 | ///
24 | public PatientInfo Patient { get; set; }
25 |
26 |
27 | ///
28 | /// Date of the Exam
29 | ///
30 | public DateTime ExamDate { get; set; }
31 |
32 | ///
33 | /// Unique ID of the current procedure
34 | ///
35 | public string ProcedureID { get; set; }
36 |
37 | public string FirstName { get; set; }
38 |
39 | public string LastName { get; set; }
40 |
41 | public int Age { get; set; }
42 |
43 | public string Procedure { get; set; }
44 |
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/license.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | =====================
3 |
4 | Copyright (c) [2020] Lior Banai
5 |
6 | Permission is hereby granted, free of charge, to any person
7 | obtaining a copy of this software and associated documentation
8 | files (the “Software”), to deal in the Software without
9 | restriction, including without limitation the rights to use,
10 | copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the
12 | Software is furnished to do so, subject to the following
13 | conditions:
14 |
15 | The above copyright notice and this permission notice shall be
16 | included in all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 | OTHER DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/HDF5-CSharp/Hdf5AttributeRW.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using HDF5CSharp.Interfaces;
4 |
5 | namespace HDF5CSharp
6 | {
7 | public class Hdf5AttributeRW : IHdf5ReaderWriter
8 | {
9 | public (bool success, Array result) ReadToArray(long groupId, string name, string alternativeName)
10 | {
11 | return Hdf5.ReadPrimitiveAttributes(groupId, name, alternativeName);
12 | }
13 |
14 | public (int success, long CreatedgroupId) WriteFromArray(long groupId, string name, Array dset)
15 | {
16 | return Hdf5.WritePrimitiveAttribute(groupId, name, dset);
17 | }
18 |
19 | public (int success, long CreatedgroupId) WriteStrings(long groupId, string name, IEnumerable collection, string datasetName = null)
20 | {
21 | return Hdf5.WriteStringAttributes(groupId, name, (string[])collection, datasetName);
22 | }
23 |
24 |
25 | public (bool success, IEnumerable) ReadStrings(long groupId, string name, string alternativeName)
26 | {
27 | return Hdf5.ReadStringAttributes(groupId, name, alternativeName);
28 | }
29 |
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/UserEventRecord.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Runtime.InteropServices;
4 | using System.Text;
5 | using HDF5CSharp.DataTypes;
6 |
7 | namespace HDF5CSharp.Example.DataTypes
8 | {
9 | [StructLayout(LayoutKind.Sequential)]
10 | [Serializable]
11 | public struct UserEventRecord
12 | {
13 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)]
14 | [Hdf5EntryName("routes")] public string Route;
15 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
16 | [Hdf5EntryName("events")] public string Event;
17 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 400)]
18 | [Hdf5EntryName("description")] public string Description;
19 | [Hdf5EntryName("timestamps")] public long Timestamp;
20 | public UserEventRecord(string route, string eventData, string description, long timestamp)
21 | {
22 | Route = route;
23 | Description = description;
24 | Event = eventData;
25 | Timestamp = timestamp;
26 | }
27 | public override string ToString() => $"time: {Timestamp}: {nameof(Route)}: {Route}, {nameof(Event)}: {Event}.";
28 |
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Viewer/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Hdf5DotnetWrapper.Viewer.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/HDF5-CSharp/DataTypes/Hdf5Recording.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 |
4 | namespace HDF5CSharp.DataTypes
5 | {
6 | [Hdf5GroupName("Recording")]
7 | public class Hdf5Recording
8 | {
9 | int _nrOfChannels;
10 |
11 | [Hdf5Save(Hdf5Save.DoNotSave)]
12 | public event PropertyChangedEventHandler PropertyChanged;
13 |
14 | public string Id { get; set; } = "";
15 | public bool ActiveFilter { get; set; } = false;
16 | public DateTime StartTime { get; set; } = DateTime.Now;
17 | public DateTime EndTime { get; set; } = DateTime.Now;
18 | public ulong NrOfSamples { get; set; } = 0;
19 | public double SampleRate { get; set; } = double.NaN;
20 | public string Physician { get; set; } = "";
21 | public string Laborant { get; set; } = "";
22 |
23 | public int NrOfChannels
24 | {
25 | get => _nrOfChannels;
26 | set
27 | {
28 | if (_nrOfChannels != value)
29 | {
30 | _nrOfChannels = value;
31 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(NrOfChannels)));
32 | }
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/CalibrationsSystemInformation.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.Collections.Generic;
4 |
5 | namespace HDF5CSharp.Example.DataTypes
6 | {
7 | [Serializable]
8 | public class CalibrationsSystemInformation
9 | {
10 | public string SystemNewHWPath { get; set; }
11 | public string SystemNewHWContent { get; set; }
12 | public string PatchBoxCalibrationPath { get; set; }
13 | public string PatchBoxCalibrationContent { get; set; }
14 | public List<(string filePath, string fileContent)> Configurations { get; set; }
15 |
16 | public CalibrationsSystemInformation()
17 | {
18 | Configurations = new List<(string filePath, string fileContent)>();
19 | SystemNewHWContent = string.Empty;
20 | SystemNewHWPath = string.Empty;
21 | PatchBoxCalibrationPath = string.Empty;
22 | PatchBoxCalibrationContent = string.Empty;
23 | }
24 |
25 | public string ToJson() => JsonConvert.SerializeObject(this);
26 | public static CalibrationsSystemInformation FromJson(string calibrationPath)
27 | => JsonConvert.DeserializeObject(calibrationPath);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/HDF5-CSharp/DataTypes/Hdf5Event.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace HDF5CSharp.DataTypes
5 | {
6 | ///
7 | ///
8 | ///
9 | [Hdf5GroupName("Event")]
10 | [StructLayout(LayoutKind.Sequential)]
11 | public struct Hdf5Event
12 | {
13 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
14 | public string Event;
15 |
16 | ///
17 | /// Time property. Datetimes can't be saved so the TimeTicks field gets saved
18 | ///
19 | [Hdf5Save(Hdf5Save.DoNotSave)]
20 | public DateTime Time
21 | {
22 | get => new DateTime(TimeTicks);
23 | set => TimeTicks = Hdf5Conversions.FromDatetime(value, Hdf5.Settings.DateTimeType);
24 | }
25 |
26 | public long TimeTicks;
27 |
28 | ///
29 | /// Duration property. Timespans can't be saved so the DurationTicks field gets saved
30 | ///
31 | [Hdf5Save(Hdf5Save.DoNotSave)]
32 | public TimeSpan Duration
33 | {
34 | get => new TimeSpan(DurationTicks);
35 | set => DurationTicks = value.Ticks;
36 | }
37 |
38 | public long DurationTicks;
39 | }
40 |
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/RPositionEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Runtime.InteropServices;
4 | using System.Text;
5 | using HDF5CSharp.DataTypes;
6 |
7 | namespace HDF5CSharp.Example.DataTypes
8 | {
9 | [StructLayout(LayoutKind.Sequential)]
10 | public struct RPositionEvent
11 | {
12 | [Hdf5EntryName("timestamp")] public ulong timestamp;
13 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)] [Hdf5EntryName("name")] public string name;
14 | [Hdf5EntryName("x")] public float x;
15 | [Hdf5EntryName("y")] public float y;
16 | [Hdf5EntryName("z")] public float z;
17 | [Hdf5EntryName("direction_x")] public float direction_x;
18 | [Hdf5EntryName("direction_y")] public float direction_y;
19 | [Hdf5EntryName("direction_z")] public float direction_z;
20 | public RPositionEvent(ulong timestamp, string name, float x, float y, float z, float direction_x, float direction_y, float direction_z)
21 | {
22 | this.timestamp = timestamp;
23 | this.name = name;
24 | this.x = x;
25 | this.y = y;
26 | this.z = z;
27 | this.direction_x = direction_x;
28 | this.direction_y = direction_y;
29 | this.direction_z = direction_z;
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/Hdf5Events.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using HDF5CSharp.DataTypes;
4 |
5 | namespace HDF5CSharp.Example.DataTypes
6 | {
7 | [Hdf5GroupName("system_events")]
8 | public class Hdf5Events
9 | {
10 | [Hdf5EntryName("timestamps")] public long[] timestamps;
11 | [Hdf5EntryName("type")] public string[] type;
12 | [Hdf5EntryName("description")] public string[] description;
13 | [Hdf5EntryName("data")] public string[] data;
14 |
15 | public Hdf5Events()
16 | {
17 | timestamps = Array.Empty();
18 | type = Array.Empty();
19 | description= Array.Empty();
20 | data= Array.Empty();
21 | }
22 | public Hdf5Events(List eventsData)
23 | {
24 | timestamps = new long[eventsData.Count];
25 | type = new string[eventsData.Count];
26 | description = new string[eventsData.Count];
27 | data = new string[eventsData.Count];
28 | for (int i = 0; i < eventsData.Count; i++)
29 | {
30 | timestamps[i] = eventsData[i].timestamp;
31 | type[i] = eventsData[i].type;
32 | description[i] = eventsData[i].description;
33 | data[i] = eventsData[i].data;
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/ECGFrame.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using MessagePack;
4 |
5 | namespace HDF5CSharp.Example.DataTypes
6 | {
7 | [Serializable]
8 | [MessagePackObject(keyAsPropertyName: false)]
9 |
10 | public class ECGFrame
11 | {
12 |
13 | [Key("packetId")] public UInt64 PacketId { get; set; }
14 | [Key("timestamp")] public long Timestamp { get; set; }
15 | [Key("KalpaClock")] public UInt64 KalpaClock { get; set; }
16 | [Key("Data")] public List> FrameData { get; set; }
17 | [Key("DataFiltered")] public List> FilteredFrameData { get; set; }
18 |
19 |
20 | [IgnoreMember] public bool IsValid;// Prior the stabilization (normalization need to be done), the frame will be raised as invalid
21 | [IgnoreMember] public bool IsTriggerToInjection;
22 |
23 | public ECGFrame()
24 | {
25 | FrameData = new List>();
26 | FilteredFrameData = new List>();
27 | IsValid = true;
28 | }
29 | public ECGFrame(List> filteredData, List> unFilteredData, long timestamp, UInt64 packetId)
30 | {
31 | PacketId = packetId;
32 | FilteredFrameData = filteredData;
33 | FrameData = unFilteredData;
34 | IsTriggerToInjection = false;
35 | Timestamp = timestamp;
36 |
37 |
38 | }
39 |
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/BlockingCollectionQueue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Threading;
5 |
6 | namespace HDF5CSharp.Example.DataTypes
7 | {
8 | public class BlockingCollectionQueue : IDisposable
9 | {
10 | private BlockingCollection items = new BlockingCollection();
11 | private long runningIndex;
12 |
13 | public int Count => items.Count;
14 |
15 | public void CompleteAdding() => items.CompleteAdding();
16 | public void Enqueue(T item)
17 | {
18 | Interlocked.Increment(ref runningIndex);
19 | items.Add(item);
20 | }
21 |
22 | public long RunningIndex => runningIndex;
23 | public IEnumerable GetConsumingEnumerable(CancellationToken cancellationToken)
24 | {
25 | foreach (var item in items.GetConsumingEnumerable())
26 | {
27 | yield return item;
28 | if (cancellationToken.IsCancellationRequested)
29 | {
30 | yield break;
31 | }
32 | }
33 | }
34 | public IEnumerable GetConsumingEnumerable()
35 | {
36 | foreach (var item in items.GetConsumingEnumerable())
37 | {
38 | yield return item;
39 | }
40 | }
41 |
42 | public void Dispose()
43 | {
44 | items?.Dispose();
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/HDF5-CSharp.UnitTests/FilesUnitTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using Microsoft.VisualStudio.TestTools.UnitTesting;
7 |
8 | namespace HDF5CSharp.UnitTests.Core
9 | {
10 | [TestClass]
11 | public class FilesUnitTests : Hdf5BaseUnitTests
12 | {
13 | private static List Errors { get; set; }
14 |
15 | public FilesUnitTests()
16 | {
17 | Errors=new List();
18 | }
19 | [TestMethod]
20 | public void TestReadStructure()
21 | {
22 | Hdf5.Settings.EnableErrorReporting(true);
23 | Hdf5Utils.LogWarning = (s) => Errors.Add(s);
24 | Hdf5Utils.LogError = (s) => Errors.Add(s);
25 | string fileName = @"testfile.h5";
26 | if (File.Exists(fileName))
27 | {
28 | var tree = Hdf5.ReadTreeFileStructure(fileName);
29 | var flat = Hdf5.ReadFlatFileStructure(fileName);
30 | File.Delete(fileName);
31 | if (Errors.Any())
32 | {
33 | foreach (string error in Errors)
34 | {
35 | Console.WriteLine(error);
36 | }
37 | }
38 | Assert.IsFalse(File.Exists(fileName));
39 | Assert.IsTrue(tree!=null);
40 | Assert.IsTrue(flat != null);
41 | }
42 | }
43 | }
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Viewer/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Hdf5DotnetWrapper.Viewer")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Hdf5DotnetWrapper.Viewer")]
13 | [assembly: AssemblyCopyright("Copyright © 2020")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("47201833-e346-46e1-b3f3-3b137b8beb0d")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/GeneralUtils.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Runtime.CompilerServices;
5 |
6 | namespace HDF5CSharp.Example
7 | {
8 |
9 | public class DateTimeComparerUpToMilliseconds : IEqualityComparer
10 | {
11 | public bool Equals(DateTime x, DateTime y) => x.EqualsUpToMilliseconds(y);
12 |
13 |
14 | public int GetHashCode(DateTime obj) => (obj.Year * 397) ^ (obj.Month * 397) ^ (obj.Day * 397) ^ (obj.Hour * 397) ^ (obj.Minute * 397) ^ (obj.Second * 397) ^ (obj.Second * 397);
15 | }
16 | public static class GeneralUtils
17 | {
18 | public static DateTimeComparerUpToMilliseconds DateTimeComparerUpToMilliseconds { get; } = new DateTimeComparerUpToMilliseconds();
19 | public static bool EqualsUpToMilliseconds(this DateTime dt1, DateTime dt2)
20 | {
21 | return dt1.Year == dt2.Year && dt1.Month == dt2.Month && dt1.Day == dt2.Day &&
22 | dt1.Hour == dt2.Hour && dt1.Minute == dt2.Minute && dt1.Second == dt2.Second && dt1.Millisecond == dt2.Millisecond;
23 | }
24 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
25 | public static (bool NonZeroFile, string Message) CheckFileSize(string filename)
26 | {
27 | FileInfo fileInfo = new FileInfo(filename);
28 | if (fileInfo.Length > 0)
29 | {
30 | string msg = $"File {filename} has size: {fileInfo.Length}";
31 | return (true, msg);
32 | }
33 | else
34 | {
35 | string msg = $"File {filename} has zero size";
36 | return (false, msg);
37 | }
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example.UnitTest/HDF5-CSharp.Example.UnitTest.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 | HDF5_CSharp.Example.UnitTest
6 |
7 | false
8 |
9 |
10 |
11 |
12 | all
13 | runtime; build; native; contentfiles; analyzers; buildtransitive
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | all
22 | runtime; build; native; contentfiles; analyzers; buildtransitive
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | Always
34 |
35 |
36 | Always
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/HDF5-CSharp/Hdf5AcquisitionFile.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using HDF5CSharp.DataTypes;
3 | using HDF5CSharp.Interfaces;
4 |
5 | namespace HDF5CSharp
6 | {
7 |
8 | [Hdf5Save(Hdf5Save.Save)]
9 | public class Hdf5AcquisitionFile : IHdf5AcquisitionFile
10 | {
11 | public Hdf5Patient Patient { get; set; }
12 | public Hdf5Recording Recording { get; set; }
13 | public Hdf5Channel[] Channels { get; set; }
14 | public Hdf5Events Events { get; set; }
15 | [Hdf5Save(Hdf5Save.DoNotSave)]
16 | public List EventList { get; private set; }
17 |
18 | [Hdf5Save(Hdf5Save.DoNotSave)]
19 | public short[,] Data { get; set; }
20 |
21 | public Hdf5AcquisitionFile()
22 | {
23 | Patient = new Hdf5Patient();
24 | Recording = new Hdf5Recording();
25 | EventList = new List();
26 | Events = new Hdf5Events();
27 |
28 | Recording.PropertyChanged += (sender, eventArgs) =>
29 | {
30 | if (eventArgs.PropertyName == nameof(Hdf5Recording.NrOfChannels))
31 | {
32 | Channels = new Hdf5Channel[Recording.NrOfChannels];
33 | }
34 | };
35 |
36 | }
37 |
38 |
39 | public void EventListToEvents()
40 | {
41 | Events = new Hdf5Events(EventList.Count);
42 | for (int i = 0; i < EventList.Count; i++)
43 | {
44 | Events.Times[i] = EventList[i].Time;
45 | Events.Durations[i] = EventList[i].Duration;
46 | Events.Events[i] = EventList[i].Event;
47 | }
48 |
49 | }
50 |
51 | }
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/HDF5-CSharp/Hdf5Conversions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.CompilerServices;
3 |
4 | namespace HDF5CSharp
5 | {
6 | public static class Hdf5Conversions
7 | {
8 | private static DateTime unix = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local);
9 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
10 | public static long FromDatetime(DateTime time, DateTimeType type)
11 | {
12 | switch (type)
13 | {
14 | case DateTimeType.Ticks:
15 | return time.Ticks;
16 | case DateTimeType.UnixTimeSeconds:
17 | return (long)(time.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, time.Kind))).TotalSeconds;
18 | case DateTimeType.UnixTimeMilliseconds:
19 | return (long)(time.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, time.Kind))).TotalMilliseconds;
20 | default:
21 | throw new ArgumentOutOfRangeException(nameof(type), type, null);
22 | }
23 | }
24 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
25 | public static DateTime ToDateTime(long value, DateTimeType type)
26 | {
27 |
28 | switch (type)
29 | {
30 | case DateTimeType.Ticks:
31 | return new DateTime(value);
32 | break;
33 | case DateTimeType.UnixTimeSeconds:
34 | return unix.AddSeconds(value);
35 | case DateTimeType.UnixTimeMilliseconds:
36 | return unix.AddMilliseconds(value);
37 | default:
38 | throw new ArgumentOutOfRangeException(nameof(type), type, null);
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/HDF5-CSharp/Hdf5Settings.cs:
--------------------------------------------------------------------------------
1 | using HDF.PInvoke;
2 | using System;
3 |
4 | namespace HDF5CSharp
5 | {
6 | public static partial class Hdf5
7 | {
8 | public static Settings Settings { get; set; }
9 |
10 |
11 | static Hdf5()
12 | {
13 | Settings = new Settings();
14 |
15 | }
16 | }
17 |
18 | public class Settings
19 | {
20 | public DateTimeType DateTimeType { get; set; }
21 | public bool LowerCaseNaming { get; set; }
22 | public bool ErrorLoggingEnable { get; private set; }
23 | public bool ThrowOnError { get; set; }
24 | public bool OverrideExistingData { get; set; }
25 | public float Version { get; set; }
26 | public Settings()
27 | {
28 | DateTimeType = DateTimeType.Ticks;
29 | ThrowOnError = true;
30 | OverrideExistingData = true;
31 | Version = 1.0f;
32 | }
33 |
34 | public Settings(DateTimeType dateTimeType, bool lowerCaseNaming, bool throwOnError, bool overrideExistingData)
35 | {
36 | DateTimeType = dateTimeType;
37 | LowerCaseNaming = lowerCaseNaming;
38 | ThrowOnError = throwOnError;
39 | OverrideExistingData = overrideExistingData;
40 | }
41 | public bool EnableErrorReporting(bool enable)
42 | {
43 | ErrorLoggingEnable = enable;
44 | if (enable)
45 | {
46 | return H5E.set_auto(H5E.DEFAULT, Hdf5Errors.ErrorDelegateMethod, IntPtr.Zero) >= 0;
47 | }
48 |
49 | return H5E.set_auto(H5E.DEFAULT, null, IntPtr.Zero) >= 0;
50 |
51 | }
52 | }
53 |
54 | public enum DateTimeType
55 | {
56 | Ticks,
57 | UnixTimeSeconds,
58 | UnixTimeMilliseconds
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/CalibrationGroup.cs:
--------------------------------------------------------------------------------
1 | using HDF5CSharp.DataTypes;
2 | using Microsoft.Extensions.Logging;
3 |
4 | namespace HDF5CSharp.Example.DataTypes
5 | {
6 | [Hdf5GroupName("calibrations")]
7 | public class CalibrationGroup : Hdf5BaseFile
8 | {
9 | [Hdf5EntryName("system_new_hw_path")]
10 | public string SystemNewHWPath { get; set; }
11 | [Hdf5EntryName("system_new_hw_content")]
12 | public string SystemNewHWContent { get; set; }
13 | [Hdf5EntryName("patch_box_calibration_Path")]
14 | public string PatchBoxCalibrationPath { get; set; }
15 | [Hdf5EntryName("patch_box_calibration_content")]
16 | public string PatchBoxCalibrationContent { get; set; }
17 |
18 | public CalibrationGroup(in long fileId, in long groupRoot, ILogger logger) : base(fileId, groupRoot, "calibrations", logger)
19 | {
20 | }
21 |
22 | public void AddCalibrationsData(CalibrationsSystemInformation calibrationsSystemInformation)
23 | {
24 | SystemNewHWPath = calibrationsSystemInformation.SystemNewHWPath;
25 | SystemNewHWContent = calibrationsSystemInformation.SystemNewHWContent;
26 | PatchBoxCalibrationPath = calibrationsSystemInformation.PatchBoxCalibrationPath;
27 | PatchBoxCalibrationContent = calibrationsSystemInformation.PatchBoxCalibrationContent;
28 | int fileNum = 0;
29 | foreach ((string filePath, string fileContent) in calibrationsSystemInformation.Configurations)
30 | {
31 | string key = $"file {fileNum++}";
32 | Hdf5.WriteStrings(GroupId, key, new[] { filePath, fileContent });
33 | Hdf5.WriteAttribute(GroupId, key, "first entry is file name. Second is content");
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/TagsGroup.cs:
--------------------------------------------------------------------------------
1 | using HDF5CSharp.DataTypes;
2 | using Microsoft.Extensions.Logging;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 |
7 | namespace HDF5CSharp.Example.DataTypes
8 | {
9 |
10 | [Hdf5GroupName("tags")]
11 | public class TagsGroup : Hdf5BaseFile, IDisposable
12 | {
13 | private Hdf5Events tags;
14 | [Hdf5Save(Hdf5Save.DoNotSave)] private List TagsData { get; set; }
15 | [Hdf5Save(Hdf5Save.DoNotSave)] private bool record;
16 | public TagsGroup(long fileId, long groupRoot, ILogger logger) : base(fileId, groupRoot, "tags", logger)
17 | {
18 | TagsData = new List();
19 |
20 | }
21 |
22 |
23 | public void Enqueue(string tagJson)
24 | {
25 |
26 | if (record)
27 | {
28 | TagsData.Add(string.IsNullOrEmpty(tagJson) ? "[]" : tagJson);
29 | }
30 | }
31 |
32 |
33 | public Task WaitForDataWritten()
34 | {
35 | record = false;
36 | Logger.LogInformation("Start write of Tags");
37 | var status = Hdf5.WriteObject(GroupId, TagsData.ToArray());
38 | Logger.LogInformation("End write of Tags with status " + status);
39 | return Task.CompletedTask;
40 | }
41 |
42 | public void StopRecording() => record = false;
43 |
44 | public void StartLogging() => record = true;
45 | public void Dispose()
46 | {
47 | try
48 | {
49 | if (!Disposed)
50 | {
51 | Hdf5.CloseGroup(GroupId);
52 | }
53 |
54 | }
55 | catch (Exception)
56 | {
57 | //nothing
58 | }
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/HDF5-CSharp.UnitTests/HDF5-CSharp.UnitTests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 | false
7 |
8 | HDF5CSharp.UnitTests.Core
9 |
10 | HDF5CSharp.UnitTests.Core
11 |
12 |
13 |
14 | AnyCPU
15 |
16 |
17 |
18 |
19 | all
20 | runtime; build; native; contentfiles; analyzers; buildtransitive
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | Always
37 |
38 |
39 | Always
40 |
41 |
42 |
43 |
44 |
45 |
46 | Always
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/.github/workflows/codacy-analysis.yml:
--------------------------------------------------------------------------------
1 | # This workflow checks out code, performs a Codacy security scan
2 | # and integrates the results with the
3 | # GitHub Advanced Security code scanning feature. For more information on
4 | # the Codacy security scan action usage and parameters, see
5 | # https://github.com/codacy/codacy-analysis-cli-action.
6 | # For more information on Codacy Analysis CLI in general, see
7 | # https://github.com/codacy/codacy-analysis-cli.
8 |
9 | name: Codacy Security Scan
10 |
11 | on:
12 | push:
13 | branches: [ master ]
14 | pull_request:
15 | branches: [ master ]
16 |
17 | jobs:
18 | codacy-security-scan:
19 | name: Codacy Security Scan
20 | runs-on: ubuntu-latest
21 | steps:
22 | # Checkout the repository to the GitHub Actions runner
23 | - name: Checkout code
24 | uses: actions/checkout@v2
25 |
26 | # Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
27 | - name: Run Codacy Analysis CLI
28 | uses: codacy/codacy-analysis-cli-action@1.1.0
29 | with:
30 | # Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
31 | # You can also omit the token and run the tools that support default configurations
32 | project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
33 | verbose: true
34 | output: results.sarif
35 | format: sarif
36 | # Adjust severity of non-security issues
37 | gh-code-scanning-compat: true
38 | # Force 0 exit code to allow SARIF file generation
39 | # This will handover control about PR rejection to the GitHub side
40 | max-allowed-issues: 2147483647
41 |
42 | # Upload the SARIF file generated in the previous step
43 | - name: Upload SARIF results file
44 | uses: github/codeql-action/upload-sarif@v1
45 | with:
46 | sarif_file: results.sarif
47 |
--------------------------------------------------------------------------------
/HDF5-CSharp/DataTypes/Attributes.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace HDF5CSharp.DataTypes
4 | {
5 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
6 | public sealed class Hdf5GroupName : Attribute
7 | {
8 |
9 | public Hdf5GroupName(string name)
10 | {
11 | Name = name;
12 | }
13 |
14 | public string Name { get; private set; }
15 | }
16 |
17 | public sealed class Hdf5KeyValuesAttributes : Attribute
18 | {
19 | public string Key { get; set; }
20 | public string[] Values { get; private set; }
21 | public Hdf5KeyValuesAttributes(string key, string[] values)
22 | {
23 | Values = values;
24 | Key = key;
25 | }
26 |
27 | }
28 | public sealed class Hdf5Attributes : Attribute
29 | {
30 |
31 | public Hdf5Attributes(string[] names)
32 | {
33 | Names = names;
34 | }
35 |
36 | public string[] Names { get; private set; }
37 | }
38 |
39 | public sealed class Hdf5Attribute : Attribute
40 | {
41 |
42 | public Hdf5Attribute(string name)
43 | {
44 | Name = name;
45 | }
46 |
47 | public string Name { get; private set; }
48 | }
49 |
50 |
51 | [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
52 | public sealed class Hdf5SaveAttribute : Attribute
53 | {
54 | public Hdf5Save SaveKind { get; } // Topic is a named parameter
55 |
56 |
57 | public Hdf5SaveAttribute(Hdf5Save saveKind) // url is a positional parameter
58 | {
59 | SaveKind = saveKind;
60 | }
61 |
62 | }
63 |
64 | [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
65 | public sealed class Hdf5EntryNameAttribute : Attribute
66 | {
67 | public string Name { get; }
68 |
69 |
70 | public Hdf5EntryNameAttribute(string name)
71 | {
72 | Name = name;
73 | }
74 |
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/HDF5-CSharp/Hdf5Groups.cs:
--------------------------------------------------------------------------------
1 | using HDF.PInvoke;
2 | using HDF5CSharp.DataTypes;
3 | using System.Collections.Generic;
4 |
5 | namespace HDF5CSharp
6 | {
7 | public static partial class Hdf5
8 | {
9 | public static bool GroupExists(long groupId, string groupName) => Hdf5Utils.ItemExists(groupId, groupName, Hdf5ElementType.Group);
10 |
11 | public static int CloseGroup(long groupId)
12 | {
13 | return H5G.close(groupId);
14 | }
15 |
16 | public static long CreateOrOpenGroup(long groupId, string groupName)
17 | {
18 |
19 | return (Hdf5Utils.ItemExists(groupId, groupName, Hdf5ElementType.Group))
20 | ? H5G.open(groupId, Hdf5Utils.NormalizedName(groupName))
21 | : H5G.create(groupId, Hdf5Utils.NormalizedName(groupName));
22 | }
23 |
24 |
25 |
26 |
27 | ///
28 | /// creates a structure of groups at once
29 | ///
30 | ///
31 | ///
32 | ///
33 | public static long CreateGroupRecursively(long groupOrFileId, string groupName)
34 | {
35 | IEnumerable grps = groupName.Split('/');
36 | long gid = groupOrFileId;
37 | groupName = "";
38 | foreach (var name in grps)
39 | {
40 | groupName = string.Concat(groupName, "/", name);
41 | gid = CreateOrOpenGroup(gid, groupName);
42 | }
43 | return gid;
44 | }
45 |
46 | public static ulong NumberOfAttributes(int groupId, string groupName)
47 | {
48 | H5O.info_t info = new H5O.info_t();
49 | var gid = H5O.get_info(groupId, ref info);
50 | return info.num_attrs;
51 | }
52 |
53 | public static H5G.info_t GroupInfo(long groupId)
54 | {
55 | H5G.info_t info = new H5G.info_t();
56 | var gid = H5G.get_info(groupId, ref info);
57 | return info;
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/ElectrodeFrame.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.CompilerServices;
3 | using MessagePack;
4 |
5 | namespace HDF5CSharp.Example.DataTypes
6 | {
7 | [Serializable]
8 | [MessagePackObject(keyAsPropertyName: true)]
9 | public class ElectrodeFrame
10 | {
11 | public (float Re, float Im)[] ComplexVoltageMatrix { get; set; } // CHANNELS * CHANNELS entries
12 | public (float Re, float Im)[] ComplexCurrentMatrix { get; set; } // CHANNELS * CHANNELS entries
13 |
14 | public long timestamp; // timestamp in unix time (milliseconds since 1.1.1970 00:00:00 - less accurate)
15 |
16 | public UInt64 PacketId = UInt64.MaxValue; // serial number of packet
17 |
18 | public UInt64 KalpaClock = UInt64.MaxValue; // Kalpa timestamp in msec? (the most accurate)
19 |
20 | public UInt64 SaturationMask;
21 |
22 | public void GenerateDummyData(int electrodeNum)
23 | {
24 | ComplexVoltageMatrix = new ValueTuple[electrodeNum * electrodeNum];
25 | ComplexCurrentMatrix = new ValueTuple[electrodeNum * electrodeNum];
26 |
27 | Random r = new Random();
28 |
29 | for (int i = 0; i < electrodeNum * electrodeNum; i++)
30 | {
31 | ComplexVoltageMatrix[i].Re = r.Next(0, 1000) / 1000.0f;
32 | ComplexVoltageMatrix[i].Im = r.Next(0, 1000) / 1000.0f;
33 | ComplexCurrentMatrix[i].Im = r.Next(0, 1000) / 1000.0f;
34 | ComplexCurrentMatrix[i].Re = r.Next(0, 1000) / 1000.0f;
35 | }
36 |
37 | PacketId = 5;
38 | KalpaClock = 1600;
39 | SaturationMask = 0;
40 | }
41 |
42 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
43 | public static byte[] Serialize(ElectrodeFrame fr) => MessagePackSerializer.Serialize(fr);
44 |
45 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
46 | public static ElectrodeFrame Deserialize(byte[] array) => MessagePackSerializer.Deserialize(array);
47 |
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/HDF5-CSharp.UnitTests/H5ETest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using HDF.PInvoke;
3 | using Microsoft.VisualStudio.TestTools.UnitTesting;
4 |
5 | namespace HDF5CSharp.UnitTests.Core
6 | {
7 | [TestClass]
8 | public class H5ETest
9 | {
10 | [TestMethod]
11 | public void H5EwalkTest1()
12 | {
13 | H5E.auto_t auto_cb = ErrorDelegateMethod;
14 | Assert.IsTrue(
15 | H5E.set_auto(H5E.DEFAULT, auto_cb, IntPtr.Zero) >= 0);
16 |
17 | H5E.walk_t walk_cb = WalkDelegateMethod;
18 | Assert.IsTrue(
19 | H5E.walk(H5E.DEFAULT, H5E.direction_t.H5E_WALK_DOWNWARD,
20 | walk_cb, IntPtr.Zero) >= 0);
21 | }
22 |
23 |
24 | [TestMethod]
25 | public void H5EwalkTest2()
26 | {
27 | // H5E.set_auto(H5E.DEFAULT, ErrorDelegateMethod, IntPtr.Zero);
28 | Assert.IsTrue(
29 | H5E.set_auto(H5E.DEFAULT, ErrorDelegateMethod, IntPtr.Zero) >= 0);
30 |
31 | H5E.walk_t walk_cb = WalkDelegateMethod;
32 | Assert.IsTrue(
33 | H5E.push(H5E.DEFAULT, "hello.c", "sqrt", 77, H5E.ERR_CLS,
34 | H5E.NONE_MAJOR, H5E.NONE_MINOR, "Hello, World!") >= 0);
35 |
36 | Assert.IsTrue(
37 | H5E.push(H5E.DEFAULT, "hello.c", "sqr", 78, H5E.ERR_CLS,
38 | H5E.NONE_MAJOR, H5E.NONE_MINOR, "Hello, World!") >= 0);
39 |
40 | Assert.IsTrue(
41 | H5E.walk(H5E.DEFAULT, H5E.direction_t.H5E_WALK_DOWNWARD,
42 | walk_cb, IntPtr.Zero) >= 0);
43 |
44 | }
45 |
46 | public static int ErrorDelegateMethod(long estack, IntPtr client_data)
47 | {
48 | H5E.walk(estack, H5E.direction_t.H5E_WALK_DOWNWARD, WalkDelegateMethod, IntPtr.Zero);
49 | return 0;
50 | }
51 |
52 | public static int WalkDelegateMethod(uint n, ref H5E.error_t err_desc, IntPtr client_data)
53 | {
54 | // log your error, e.g. logger.LogInformation(err_desc.desc);
55 | return 0;
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/HDF5-CSharp/DataProducerConsumer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Diagnostics;
4 | using System.Threading;
5 |
6 | namespace HDF5CSharp
7 | {
8 | public class DataProducerConsumer : IDisposable
9 | {
10 | private BlockingCollection _queue = new BlockingCollection();
11 | private readonly Action _action;
12 |
13 | public DataProducerConsumer(Action action)
14 | {
15 | _action = action;
16 |
17 | var thread = new Thread(StartConsuming)
18 | {
19 | IsBackground = true
20 | };
21 | thread.Start();
22 | }
23 |
24 | public void Dispose()
25 | {
26 | Dispose(true);
27 | GC.SuppressFinalize(this);
28 | }
29 |
30 | protected virtual void Dispose(bool disposing)
31 | {
32 | if (disposing)
33 | {
34 | _queue.Dispose();
35 | }
36 | }
37 |
38 | public void Done()
39 | {
40 | _queue.CompleteAdding();
41 | }
42 |
43 | public void Produce(T item)
44 | {
45 | _queue.Add(item);
46 | }
47 |
48 | private void StartConsuming()
49 | {
50 | while (!_queue.IsCompleted)
51 | {
52 | try
53 | {
54 | _queue.TryTake(out T data);
55 | if (data != null)
56 | {
57 | Debug.WriteLine($"item {_queue.Count + 1} in queue will be processed");
58 | _action(data);
59 | }
60 |
61 | }
62 | catch (InvalidOperationException ex)
63 | {
64 | Debug.WriteLine($"Work queue on thread {0} has been closed. {ex}", Thread.CurrentThread.ManagedThreadId);
65 | }
66 | }
67 | IsDone?.Invoke(this, new EventArgs());
68 | Dispose();
69 | }
70 |
71 | public event EventHandler IsDone;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/Hdf5BaseFile.cs:
--------------------------------------------------------------------------------
1 | using HDF5CSharp.DataTypes;
2 | using Microsoft.Extensions.Logging;
3 | using System;
4 |
5 | namespace HDF5CSharp.Example.DataTypes
6 | {
7 | [Serializable]
8 | public abstract class Hdf5BaseFile
9 | {
10 | [Hdf5Save(Hdf5Save.DoNotSave)] private long FileId { get; }
11 | [Hdf5Save(Hdf5Save.DoNotSave)] protected long GroupRoot { get; }
12 | [Hdf5Save(Hdf5Save.DoNotSave)] protected string GroupName { get; }
13 | [Hdf5Save(Hdf5Save.DoNotSave)] protected long GroupId { get; }
14 | [Hdf5Save(Hdf5Save.DoNotSave)] protected bool Disposed { get; set; }
15 | [Hdf5Save(Hdf5Save.DoNotSave)] protected ILogger Logger { get; }
16 | protected Hdf5BaseFile(in long fileId, in long groupRoot, in string groupName, ILogger logger)
17 | {
18 | FileId = fileId;
19 | GroupRoot = groupRoot;
20 | GroupName = groupName;
21 | Logger = logger;
22 | GroupId = Hdf5.CreateOrOpenGroup(groupRoot, GroupName);
23 |
24 | }
25 | protected Hdf5BaseFile()
26 | {
27 |
28 | }
29 |
30 | public void FlushData()
31 | {
32 | if (Disposed)
33 | {
34 | return;
35 | }
36 |
37 | try
38 | {
39 | Hdf5.WriteObject(GroupRoot, this, GroupName);
40 | Hdf5.Flush(GroupId, HDF.PInvoke.H5F.scope_t.LOCAL);
41 | }
42 | catch (Exception e)
43 | {
44 | Logger?.LogError(e, $"Error FlushData: {e.Message}. Type: {GetType()}");
45 | }
46 | }
47 | public void FlushDataAndCloseObject()
48 | {
49 | try
50 | {
51 | if (Disposed)
52 | {
53 | return;
54 | }
55 |
56 | FlushData();
57 | Hdf5.CloseGroup(GroupId);
58 | }
59 | catch (Exception e)
60 | {
61 | Logger?.LogError(e, $"Error FlushDataAndCloseObject: {e.Message}. Type: {GetType()}");
62 | }
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/UserEventsGroup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using HDF5CSharp.DataTypes;
7 | using Microsoft.Extensions.Logging;
8 |
9 | namespace HDF5CSharp.Example.DataTypes
10 | {
11 | public class Hdf5UserEvents
12 | {
13 | [Hdf5EntryName("user_events")] public UserEventRecord[] Events { get; set; }
14 | public Hdf5UserEvents(List eventsData)
15 | {
16 | Events = eventsData.ToArray();
17 | }
18 |
19 | public Hdf5UserEvents()
20 | {
21 |
22 | }
23 | }
24 |
25 | public class UserEventsGroup : Hdf5BaseFile, IDisposable
26 | {
27 | [Hdf5Save(Hdf5Save.DoNotSave)] private List userEventsData;
28 |
29 | public UserEventsGroup(long fileId, long groupRoot, ILogger logger) : base(fileId, groupRoot, Constants.EventGroupName, logger)
30 | {
31 | userEventsData = new List();
32 | }
33 |
34 | public void Enqueue(UserEventRecord userEventRecord)
35 | {
36 | userEventsData.Add(userEventRecord);
37 | }
38 |
39 | public Task WaitForDataWritten()
40 | {
41 | if (!userEventsData.Any())
42 | {
43 | Logger.LogWarning("No user event to write to H5 file");
44 | return Task.CompletedTask;
45 | }
46 | var dataToWrite = userEventsData;
47 | userEventsData = new List();
48 | Hdf5UserEvents eventsToH5 = new Hdf5UserEvents(dataToWrite);
49 | Logger.LogInformation("Start write of User Events");
50 | var status = Hdf5.WriteObject(GroupRoot, eventsToH5, Constants.EventGroupName);
51 | Logger.LogInformation("End write of User Events with status " + status);
52 | return Task.CompletedTask;
53 | }
54 | public void Dispose()
55 | {
56 | try
57 | {
58 | if (!Disposed)
59 | {
60 | Hdf5.CloseGroup(GroupId);
61 | }
62 |
63 | }
64 | catch (Exception)
65 | {
66 | //nothing
67 | }
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Viewer/Form1.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace Hdf5DotnetWrapper.Viewer
2 | {
3 | partial class Form1
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.hdF5FileLoader1 = new Hdf5DotnetWrapper.Viewer.HDF5FileLoader();
32 | this.SuspendLayout();
33 | //
34 | // hdF5FileLoader1
35 | //
36 | this.hdF5FileLoader1.Dock = System.Windows.Forms.DockStyle.Fill;
37 | this.hdF5FileLoader1.Location = new System.Drawing.Point(0, 0);
38 | this.hdF5FileLoader1.Name = "hdF5FileLoader1";
39 | this.hdF5FileLoader1.Size = new System.Drawing.Size(800, 506);
40 | this.hdF5FileLoader1.TabIndex = 0;
41 | //
42 | // Form1
43 | //
44 | this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 18F);
45 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
46 | this.ClientSize = new System.Drawing.Size(800, 506);
47 | this.Controls.Add(this.hdF5FileLoader1);
48 | this.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
49 | this.Name = "Form1";
50 | this.Text = "Form1";
51 | this.ResumeLayout(false);
52 |
53 | }
54 |
55 | #endregion
56 |
57 | private HDF5FileLoader hdF5FileLoader1;
58 | }
59 | }
60 |
61 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/AssemblyInformationRecord.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Runtime.InteropServices;
4 | using System.Text;
5 | using HDF5CSharp.DataTypes;
6 |
7 | namespace HDF5CSharp.Example.DataTypes
8 | {
9 | [StructLayout(LayoutKind.Sequential)]
10 | [Serializable]
11 | public struct AssemblyInformationRecord
12 | {
13 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 120)]
14 | [Hdf5EntryName("file_name")] public readonly string FileName;
15 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
16 | [Hdf5EntryName("file_version")] public readonly string FileVersion;
17 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
18 | [Hdf5EntryName("product_version")] public readonly string ProductVersion;
19 | [Hdf5EntryName("date_modified")] public readonly long DateModified;
20 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
21 | [Hdf5EntryName("date_modified_time")] public readonly string DateModifiedDisplayName;
22 | public AssemblyInformationRecord(string filename, string fileVersion, string productVersion, long dateModified)
23 | {
24 | FileName = filename;
25 | FileVersion = fileVersion;
26 | ProductVersion = productVersion;
27 | DateModified = dateModified;
28 | DateModifiedDisplayName = DateTimeOffset.FromUnixTimeMilliseconds(dateModified).ToString();
29 | }
30 |
31 | public bool Equals(AssemblyInformationRecord other) => FileName == other.FileName && FileVersion == other.FileVersion && ProductVersion == other.ProductVersion && DateModified == other.DateModified;
32 |
33 | public override bool Equals(object obj) => obj is AssemblyInformationRecord other && Equals(other);
34 |
35 | public override int GetHashCode()
36 | {
37 | unchecked
38 | {
39 | var hashCode = (FileName != null ? FileName.GetHashCode() : 0);
40 | hashCode = (hashCode * 397) ^ (FileVersion != null ? FileVersion.GetHashCode() : 0);
41 | hashCode = (hashCode * 397) ^ (ProductVersion != null ? ProductVersion.GetHashCode() : 0);
42 | hashCode = (hashCode * 397) ^ DateModified.GetHashCode();
43 | return hashCode;
44 | }
45 | }
46 |
47 | public override string ToString() => $"{nameof(FileName)}: {FileName}, {nameof(FileVersion)}: {FileVersion}, {nameof(ProductVersion)}: {ProductVersion}, {nameof(DateModified)}: {DateModified}";
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/ProcedureInformation.cs:
--------------------------------------------------------------------------------
1 | using HDF5CSharp.DataTypes;
2 | using Microsoft.Extensions.Logging;
3 | using System;
4 |
5 | namespace HDF5CSharp.Example.DataTypes
6 | {
7 | [Hdf5Attributes(new[] { "General information of the procedure" })]
8 | [Hdf5GroupName("procedure_information")]
9 | public class ProcedureInformation : Hdf5BaseFile, IEquatable
10 | {
11 | [Hdf5EntryName("procedure_directory")]
12 | public string ProcedureDirectory { get; set; }
13 | [Hdf5("the type of procedure")]
14 | [Hdf5EntryName("procedure_type")]
15 | public string ProcedureType { get; set; }
16 | [Hdf5EntryName("start_datetime")]
17 | public DateTime StartDateTime { get; set; }
18 | [Hdf5EntryName("end_datetime")]
19 | public DateTime EndDateTime { get; set; }
20 | [Hdf5EntryName("procedure_id")]
21 | public string ProcedureID { get; set; }
22 |
23 | public ProcedureInformation(long fileId, long groupRoot, ILogger logger) : base(fileId, groupRoot, "procedure_information", logger)
24 | {
25 | ProcedureDirectory = string.Empty;
26 | ProcedureType = string.Empty;
27 | }
28 |
29 | public ProcedureInformation()
30 | {
31 |
32 | }
33 |
34 | public bool Equals(ProcedureInformation other)
35 | {
36 | if (ReferenceEquals(null, other))
37 | {
38 | return false;
39 | }
40 |
41 | if (ReferenceEquals(this, other))
42 | {
43 | return true;
44 | }
45 |
46 | return ProcedureDirectory == other.ProcedureDirectory && ProcedureType == other.ProcedureType &&
47 | StartDateTime.EqualsUpToMilliseconds(other.StartDateTime) && EndDateTime.EqualsUpToMilliseconds(other.EndDateTime) &&
48 | ProcedureID == other.ProcedureID;
49 |
50 | }
51 |
52 | public override bool Equals(object obj)
53 | {
54 | if (ReferenceEquals(null, obj))
55 | {
56 | return false;
57 | }
58 |
59 | if (ReferenceEquals(this, obj))
60 | {
61 | return true;
62 | }
63 |
64 | if (obj.GetType() != this.GetType())
65 | {
66 | return false;
67 | }
68 |
69 | return Equals((ProcedureInformation)obj);
70 | }
71 |
72 | public override int GetHashCode()
73 | {
74 | return (ProcedureDirectory.GetHashCode() * 397) ^ (ProcedureType.GetHashCode() * 397) ^
75 | (StartDateTime.GetHashCode() * 397) ^ (EndDateTime.GetHashCode() * 397) ^
76 | (ProcedureID.GetHashCode() * 397);
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/EventGroup.cs:
--------------------------------------------------------------------------------
1 | using HDF5CSharp.DataTypes;
2 | using Microsoft.Extensions.Logging;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 |
7 | namespace HDF5CSharp.Example.DataTypes
8 | {
9 | [Hdf5GroupName("events")]
10 | public class EventGroup : Hdf5BaseFile, IDisposable
11 | {
12 |
13 | private Hdf5Events events;
14 | [Hdf5Save(Hdf5Save.DoNotSave)] private List SystemEventSamplesData { get; set; }
15 | [Hdf5Save(Hdf5Save.DoNotSave)] private bool record;
16 | public EventGroup(long fileId, long groupRoot, ILogger logger) : base(fileId, groupRoot, "events", logger)
17 | {
18 | SystemEventSamplesData = new List();
19 | // SystemEvents = new ChunkedDataset("system_events", GroupId);
20 | // UserTags = new ChunkedDataset("user_tags", GroupId);
21 | // SystemTaskWriter = Task.Factory.StartNew(() =>
22 | //{
23 |
24 | // completed = false;
25 | // foreach (SystemEvent data in SystemEventSamplesData.GetConsumingEnumerable())
26 | // {
27 | // SystemEvent[,] events = new SystemEvent[1, 1];
28 | // events[0, 0] = data;
29 | // SystemEvents.AppendOrCreateDataset(events);
30 | // }
31 | // Flush(); //end of data sample. flush data
32 | //});
33 | }
34 |
35 |
36 | public void Dispose()
37 | {
38 | try
39 | {
40 | if (!Disposed)
41 | {
42 | Hdf5.CloseGroup(GroupId);
43 | }
44 |
45 | }
46 | catch (Exception)
47 | {
48 | //nothing
49 | }
50 | }
51 |
52 | public void Enqueue(SystemEventModel systemEvent)
53 | {
54 |
55 | if (record)
56 | {
57 | SystemEvent hdf5SystemEvent = new SystemEvent(systemEvent.TimeStamp, systemEvent.SystemEventType.ToString(), "", systemEvent.EventData);
58 | SystemEventSamplesData.Add(hdf5SystemEvent);
59 | }
60 | }
61 |
62 |
63 | public Task WaitForDataWritten()
64 | {
65 | record = false;
66 | Logger.LogInformation("Start write of system events");
67 | events = new Hdf5Events(SystemEventSamplesData);
68 | var status = Hdf5.WriteObject(GroupId, events);
69 | Logger.LogInformation("End write of system events with status " + status);
70 | return Task.CompletedTask;
71 | }
72 |
73 | public void StopRecording() => record = false;
74 |
75 | public void StartLogging() => record = true;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | name: "CodeQL"
7 |
8 | on:
9 | push:
10 | branches: [master]
11 | pull_request:
12 | # The branches below must be a subset of the branches above
13 | branches: [master]
14 | schedule:
15 | - cron: '0 11 * * 5'
16 |
17 | jobs:
18 | analyze:
19 | name: Analyze
20 | runs-on: windows-latest
21 |
22 | strategy:
23 | fail-fast: false
24 | matrix:
25 | # Override automatic language detection by changing the below list
26 | # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
27 | language: ['csharp']
28 | # Learn more...
29 | # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
30 |
31 | steps:
32 | - name: Checkout repository
33 | uses: actions/checkout@v2
34 | with:
35 | # We must fetch at least the immediate parents so that if this is
36 | # a pull request then we can checkout the head.
37 | fetch-depth: 2
38 |
39 | # If this run was triggered by a pull request event, then checkout
40 | # the head of the pull request instead of the merge commit.
41 | - run: git checkout HEAD^2
42 | if: ${{ github.event_name == 'pull_request' }}
43 |
44 | # Initializes the CodeQL tools for scanning.
45 | - name: Initialize CodeQL
46 | uses: github/codeql-action/init@v1
47 | with:
48 | languages: ${{ matrix.language }}
49 | # If you wish to specify custom queries, you can do so here or in a config file.
50 | # By default, queries listed here will override any specified in a config file.
51 | # Prefix the list here with "+" to use these queries and those in the config file.
52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main
53 |
54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
55 | # If this step fails, then you should remove it and run the build manually (see below)
56 | - name: Autobuild
57 | uses: github/codeql-action/autobuild@v1
58 |
59 | # ℹ️ Command-line programs to run using the OS shell.
60 | # 📚 https://git.io/JvXDl
61 |
62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
63 | # and modify them (or add more) to build your code if your project
64 | # uses a compiled language
65 |
66 | #- run: |
67 | # make bootstrap
68 | # make release
69 |
70 | - name: Perform CodeQL Analysis
71 | uses: github/codeql-action/analyze@v1
72 |
--------------------------------------------------------------------------------
/azure-pipelines.yml:
--------------------------------------------------------------------------------
1 | # .NET Desktop
2 | # Build and run tests for .NET Desktop or Windows classic desktop solutions.
3 | # Add steps that publish symbols, save build artifacts, and more:
4 | # https://docs.microsoft.com/azure/devops/pipelines/apps/windows/dot-net
5 |
6 | trigger:
7 | - master
8 |
9 | pool:
10 | vmImage: 'windows-latest'
11 |
12 | variables:
13 | solution: '**/*.sln'
14 | buildPlatform: 'Any CPU'
15 | buildConfiguration: 'Release'
16 |
17 | steps:
18 | - task: NuGetToolInstaller@1
19 |
20 | - task: NuGetCommand@2
21 | inputs:
22 | restoreSolution: '$(solution)'
23 |
24 | - task: VSBuild@1
25 | inputs:
26 | solution: '$(solution)'
27 | platform: '$(buildPlatform)'
28 | configuration: '$(buildConfiguration)'
29 |
30 | # Run all tests with "/p:CollectCoverage=true /p:CoverletOutputFormat=cobertura" to generate the code coverage file
31 | - task: DotNetCoreCLI@2
32 | displayName: dotnet test
33 | inputs:
34 | command: test
35 | arguments: '--configuration $(BuildConfiguration) /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura'
36 | projects: 'HDF5-CSharp.Example.UnitTest/*.csproj'
37 |
38 |
39 | - task: DotNetCoreCLI@2
40 | displayName: dotnet test
41 | inputs:
42 | command: test
43 | arguments: '--configuration $(BuildConfiguration) /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura'
44 | projects: 'HDF5-CSharp.UnitTests/*.csproj'
45 |
46 | # Generate the report using ReportGenerator (https://github.com/danielpalme/ReportGenerator)
47 | # First install the tool on the machine, then run it
48 | - script: |
49 | dotnet tool install -g dotnet-reportgenerator-globaltool
50 | reportgenerator -reports:$(Build.SourcesDirectory)/HDF5-CSharp.Example.UnitTest/coverage.cobertura.xml -targetdir:$(Build.SourcesDirectory)/CodeCoverage -reporttypes:HtmlInline_AzurePipelines;Cobertura
51 | displayName: Create Code coverage report example project
52 |
53 |
54 | # Generate the report using ReportGenerator (https://github.com/danielpalme/ReportGenerator)
55 | # First install the tool on the machine, then run it
56 | - script: |
57 | dotnet tool install -g dotnet-reportgenerator-globaltool
58 | reportgenerator -reports:$(Build.SourcesDirectory)/HDF5-CSharp.UnitTests/coverage.cobertura.xml -targetdir:$(Build.SourcesDirectory)/CodeCoverage -reporttypes:HtmlInline_AzurePipelines;Cobertura
59 | displayName: Create Code coverage report
60 |
61 |
62 |
63 |
64 | # Publish the code coverage result (summary and web site)
65 | # The summary allows to view the coverage percentage in the summary tab
66 | # The web site allows to view which lines are covered directly in Azure Pipeline
67 | - task: PublishCodeCoverageResults@1
68 | displayName: 'Publish code coverage'
69 | inputs:
70 | codeCoverageTool: Cobertura
71 | summaryFileLocation: '$(Build.SourcesDirectory)/CodeCoverage/Cobertura.xml'
72 | reportDirectory: '$(Build.SourcesDirectory)/CodeCoverage'
73 |
--------------------------------------------------------------------------------
/HDF5-CSharp/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace HDF5CSharp.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("HDF5CSharp.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/HDF5-CSharp/DataTypes/DataTypes.cs:
--------------------------------------------------------------------------------
1 | using HDF.PInvoke;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | namespace HDF5CSharp.DataTypes
6 | {
7 | public enum Hdf5ElementType
8 | {
9 | Unknown = 0,
10 | Group,
11 | Dataset,
12 | Attribute
13 | }
14 | public abstract class Hdf5ElementBase
15 | {
16 | public string Name { get; set; }
17 | public Hdf5ElementType Type { get; set; }
18 | public bool IsLazyLoading { get; }
19 |
20 | public Hdf5ElementBase Parent { get; set; }
21 | public long Id { get; set; }
22 | protected bool HasLoadedOnce { get; set; }
23 | public abstract string GetPath();
24 | public abstract string GetDisplayName();
25 | public abstract IEnumerable GetChildren();
26 | protected abstract long GetId(long fileId);
27 | protected abstract void CloseId(long id);
28 |
29 | public Hdf5ElementBase(string name, Hdf5ElementType type, Hdf5ElementBase parent,long id, bool isLazyLoading)
30 | {
31 | Name = name;
32 | Type = type;
33 | Parent = parent;
34 | IsLazyLoading = isLazyLoading;
35 | Id = id;
36 | }
37 |
38 | public override string ToString() => $"{nameof(Name)}: {Name} ({Type}) ID:{Id}";
39 | }
40 |
41 | public class Hdf5Element : Hdf5ElementBase
42 | {
43 | private List Children { get; }
44 | public Hdf5Element(string name, Hdf5ElementType type, Hdf5ElementBase parent, long id, bool isLazyLoading) : base(name, type, parent,id, isLazyLoading)
45 | {
46 | Children = new List();
47 | }
48 |
49 | public bool HasChildren => Children.Any();
50 |
51 | public override string GetPath()
52 | {
53 | return Name;
54 | }
55 |
56 | public override string GetDisplayName()
57 | {
58 | return Name;
59 | }
60 |
61 | public override IEnumerable GetChildren()
62 | {
63 | return Children.ToList();
64 | }
65 |
66 | protected override long GetId(long fileId)
67 | {
68 | return H5G.open(fileId, GetPath());
69 | }
70 |
71 | protected override void CloseId(long id)
72 | {
73 | if (H5I.is_valid(id) > 0)
74 | {
75 | H5G.close(id);
76 | }
77 | }
78 |
79 | public void AddChild(Hdf5Element child)
80 | {
81 | Children.Add(child);
82 | }
83 |
84 | public Hdf5Element GetChildWithName(string childName)
85 | {
86 | var child = Children.FirstOrDefault(c => c.Name == childName);
87 | if (child != null)
88 | {
89 | return child;
90 | }
91 |
92 | var subChildren = Children.Where(c => c.HasChildren).Select(c => c.GetChildWithName(childName));
93 | return subChildren.FirstOrDefault();
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Viewer/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Hdf5DotnetWrapper.Viewer.Properties
12 | {
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// Returns the cached ResourceManager instance used by this class.
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Hdf5DotnetWrapper.Viewer.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// Overrides the current thread's CurrentUICulture property for all
56 | /// resource lookups using this strongly typed resource class.
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/Patient.cs:
--------------------------------------------------------------------------------
1 | using HDF5CSharp.DataTypes;
2 | using Microsoft.Extensions.Logging;
3 | using System;
4 |
5 | namespace HDF5CSharp.Example.DataTypes
6 | {
7 | [Serializable]
8 | [Hdf5GroupName("patient")]
9 | public class Patient : Hdf5BaseFile, IDisposable, IEquatable
10 | {
11 | [Hdf5EntryName("first_name")]
12 | public string FirstName { get; set; }
13 | [Hdf5EntryName("last_name")]
14 | public string LastName { get; set; }
15 | public string Id { get; set; }
16 |
17 | public string Gender { get; set; }
18 | public float Age { get; set; }
19 | public double Height { get; set; }
20 | public double Weight { get; set; }
21 | [Hdf5EntryName("exam_date")]
22 | public DateTime ExamDate { get; set; }
23 |
24 | public Patient(long fileId, long groupRoot, ILogger logger) : base(fileId, groupRoot, "patient", logger)
25 | {
26 | FirstName = string.Empty;
27 | LastName = string.Empty;
28 | Id = string.Empty;
29 | Gender = string.Empty;
30 |
31 | }
32 | public Patient()
33 | {
34 |
35 | }
36 |
37 | public void Dispose()
38 | {
39 | try
40 | {
41 | if (!Disposed)
42 | {
43 | Hdf5.CloseGroup(GroupId);
44 | Disposed = true;
45 | }
46 | }
47 | catch (Exception e)
48 | {
49 | Logger?.LogError($"Error closing file: {e}");
50 | }
51 |
52 | }
53 |
54 | public bool Equals(Patient other)
55 | {
56 | if (ReferenceEquals(null, other))
57 | {
58 | return false;
59 | }
60 |
61 | if (ReferenceEquals(this, other))
62 | {
63 | return true;
64 | }
65 |
66 | return FirstName == other.FirstName && LastName == other.LastName && Id == other.Id &&
67 | Gender == other.Gender && Age.Equals(other.Age) && Height.Equals(other.Height) &&
68 | Weight.Equals(other.Weight) && ExamDate.EqualsUpToMilliseconds(other.ExamDate);
69 | }
70 |
71 | public override bool Equals(object obj)
72 | {
73 | if (ReferenceEquals(null, obj))
74 | {
75 | return false;
76 | }
77 |
78 | if (ReferenceEquals(this, obj))
79 | {
80 | return true;
81 | }
82 |
83 | if (obj.GetType() != this.GetType())
84 | {
85 | return false;
86 | }
87 |
88 | return Equals((Patient)obj);
89 | }
90 |
91 | public override int GetHashCode()
92 | {
93 | return (FirstName.GetHashCode() * 397) ^ (LastName.GetHashCode() * 397) ^ (Id.GetHashCode() * 397) ^
94 | (Gender.GetHashCode() * 397) ^ (Age.GetHashCode() * 397) ^ (Height.GetHashCode() * 397) ^
95 | (Weight.GetHashCode() * 397) ^ (ExamDate.GetHashCode() * 397);
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/HDF5-CSharp.UnitTests/Hdf5GroupTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Linq;
4 | using HDF.PInvoke;
5 | using Microsoft.VisualStudio.TestTools.UnitTesting;
6 |
7 | namespace HDF5CSharp.UnitTests.Core
8 | {
9 | public partial class Hdf5UnitTests
10 | {
11 | [TestMethod]
12 | public void WriteAndReadGroupsWithDataset()
13 | {
14 | string filename = Path.Combine(folder, "testGroups.H5");
15 |
16 | try
17 | {
18 | var fileId = Hdf5.CreateFile(filename);
19 | Assert.IsTrue(fileId > 0);
20 | var dset = dsets.First();
21 |
22 | var groupId = H5G.create(fileId, Hdf5Utils.NormalizedName("/A")); ///B/C/D/E/F/G/H
23 | Hdf5.WriteDataset(groupId, Hdf5Utils.NormalizedName("test"), dset);
24 | var subGroupId = Hdf5.CreateOrOpenGroup(groupId, Hdf5Utils.NormalizedName("C"));
25 | var subGroupId2 = Hdf5.CreateOrOpenGroup(groupId, Hdf5Utils.NormalizedName("/D")); // will be saved at the root location
26 | dset = dsets.Skip(1).First();
27 | Hdf5.WriteDataset(subGroupId, Hdf5Utils.NormalizedName("test2"), dset);
28 | Hdf5.CloseGroup(subGroupId);
29 | Hdf5.CloseGroup(subGroupId2);
30 | Hdf5.CloseGroup(groupId);
31 | groupId = H5G.create(fileId, Hdf5Utils.NormalizedName("/A/B")); ///B/C/D/E/F/G/H
32 | dset = dsets.Skip(1).First();
33 | Hdf5.WriteDataset(groupId, Hdf5Utils.NormalizedName("test"), dset);
34 | Hdf5.CloseGroup(groupId);
35 |
36 | groupId = Hdf5.CreateGroupRecursively(fileId, Hdf5Utils.NormalizedName("A/B/C/D/E/F/I"));
37 | Hdf5.CloseGroup(groupId);
38 | Hdf5.CloseFile(fileId);
39 |
40 |
41 | fileId = Hdf5.OpenFile(filename);
42 | Assert.IsTrue(fileId > 0);
43 | fileId = Hdf5.OpenFile(filename);
44 |
45 | groupId = H5G.open(fileId, Hdf5Utils.NormalizedName("/A/B"));
46 | double[,] dset2 = (double[,])Hdf5.ReadDataset(groupId, Hdf5Utils.NormalizedName( "test")).result;
47 | CompareDatasets(dset, dset2);
48 | Assert.IsTrue(Hdf5.CloseGroup(groupId) >= 0);
49 | groupId = H5G.open(fileId, Hdf5Utils.NormalizedName("/A/C"));
50 | dset2 = (double[,])Hdf5.ReadDataset(groupId, Hdf5Utils.NormalizedName("test2")).result;
51 | CompareDatasets(dset, dset2);
52 | Assert.IsTrue(Hdf5.CloseGroup(groupId) >= 0);
53 | bool same = dset == dset2;
54 | dset = dsets.First();
55 | dset2 = (double[,])Hdf5.ReadDataset(fileId, Hdf5Utils.NormalizedName("/A/test")).result;
56 | CompareDatasets(dset, dset2);
57 | Assert.IsTrue(Hdf5Utils.ItemExists(fileId, Hdf5Utils.NormalizedName( "A/B/C/D/E/F/I"),DataTypes.Hdf5ElementType.Dataset));
58 |
59 | Assert.IsTrue(Hdf5.CloseFile(fileId) == 0);
60 |
61 | }
62 | catch (Exception ex)
63 | {
64 | CreateExceptionAssert(ex);
65 | }
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/.github/workflows/dotnet-core-desktop.yml:
--------------------------------------------------------------------------------
1 | name: .NET Core Desktop
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 |
11 | build:
12 |
13 | strategy:
14 | matrix:
15 | configuration: [Release, Debug]
16 |
17 | runs-on: windows-latest # For a list of available runner types, refer to
18 | # https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on
19 |
20 | env:
21 | Solution_Name: HDF5-CSharp.sln # Replace with your solution name, i.e. MyWpfApp.sln.
22 | Test_Project_Path: HDF5-CSharp.UnitTests\HDF5-CSharp.UnitTests.csproj # Replace with the path to your test project, i.e. MyWpfApp.Tests\MyWpfApp.Tests.csproj.
23 |
24 | steps:
25 | - name: Checkout
26 | uses: actions/checkout@v2
27 | with:
28 | fetch-depth: 0
29 |
30 | # Install the .NET Core workload
31 | - name: Install .NET Core
32 | uses: actions/setup-dotnet@v1
33 | with:
34 | dotnet-version: 3.1.101
35 |
36 | # Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild
37 | - name: Setup MSBuild.exe
38 | uses: microsoft/setup-msbuild@v1.0.2
39 |
40 | # Restore the application to populate the obj folder with RuntimeIdentifiers
41 | - name: Restore the application
42 | run: msbuild $env:Solution_Name /t:Restore /p:Configuration=$env:Configuration
43 | env:
44 | Configuration: ${{ matrix.configuration }}
45 |
46 | # Buid the application
47 | - name: Build the application
48 | run: msbuild $env:Solution_Name /t:Rebuild /p:Configuration=$env:Configuration
49 | env:
50 | Configuration: ${{ matrix.configuration }}
51 | # Execute all unit tests in the solution
52 | - name: Execute unit tests
53 | run: dotnet test
54 |
55 | # Publish Artifacts
56 | - name: 'Publish Artifacts'
57 | uses: actions/upload-artifact@v1.0.0
58 | with:
59 | name: 'artifactory'
60 | path: ./HDF5-CSharp/bin/${{ matrix.configuration }}
61 | push-nuget:
62 | name: 'Push NuGet Packages'
63 | needs: build
64 | runs-on: windows-latest
65 | steps:
66 | - name: 'Download Artifact'
67 | uses: actions/download-artifact@v1
68 | with:
69 | name: 'artifactory'
70 | - name: 'Dotnet NuGet Push'
71 | run: |
72 | Get-ChildItem .\artifactory -Filter *.nupkg |
73 | Where-Object { !$_.Name.Contains('preview') } |
74 | ForEach-Object { dotnet nuget push $_ --source https://api.nuget.org/v3/index.json --skip-duplicate --api-key ${{secrets.NUGET_API_KEY}} }
75 | shell: pwsh
76 |
77 | - name: Setup NuGet.exe for use with actions
78 | uses: NuGet/setup-nuget@v1.0.5
79 |
80 | - name: Add private GitHub registry to NuGet
81 | run: nuget sources add -name "GPR" -Source https://nuget.pkg.github.com/LiorBanai/index.json -Username LiorBanai -Password ${{ secrets.GITHUB_TOKEN }}
82 |
83 | - name: 'Dotnet NuGet Push to github registry'
84 | run: |
85 | Get-ChildItem .\artifactory -Filter *.nupkg |
86 | Where-Object { !$_.Name.Contains('preview') } |
87 | ForEach-Object { nuget push $_ -Source "GPR" -SkipDuplicate }
88 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/SystemEventGroup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 | using HDF5CSharp.DataTypes;
8 | using Microsoft.Extensions.Logging;
9 |
10 | namespace HDF5CSharp.Example.DataTypes
11 | {
12 | public class Hdf5SystemEvents
13 | {
14 | [Hdf5EntryName("system_events")] public SystemEvent[] Events { get; set; }
15 | public Hdf5SystemEvents(List eventsData)
16 | {
17 | Events = eventsData.ToArray();
18 | }
19 |
20 | public Hdf5SystemEvents()
21 | {
22 |
23 | }
24 | }
25 | public class SystemEventGroup : Hdf5BaseFile, IDisposable
26 | {
27 | [Hdf5Save(Hdf5Save.DoNotSave)] private ReaderWriterLockSlim LockSlim { get; }
28 | [Hdf5Save(Hdf5Save.DoNotSave)] private List SystemEventSamplesData { get; set; }
29 | [Hdf5Save(Hdf5Save.DoNotSave)] private bool record;
30 | public SystemEventGroup(long fileId, long groupRoot, ILogger logger) : base(fileId, groupRoot, "events", logger)
31 | {
32 | SystemEventSamplesData = new List();
33 | LockSlim = new ReaderWriterLockSlim();
34 | }
35 |
36 |
37 | public void Dispose()
38 | {
39 | try
40 | {
41 | if (!Disposed)
42 | {
43 | Hdf5.CloseGroup(GroupId);
44 | }
45 |
46 | }
47 | catch (Exception e)
48 | {
49 | Logger.LogError(e, $"Error closing System Event group: {e.Message}");
50 | }
51 | }
52 |
53 | public void Enqueue(SystemEventModel systemEvent)
54 | {
55 |
56 | if (record)
57 | {
58 | SystemEvent hdf5SystemEvent = new SystemEvent(systemEvent.TimeStamp, systemEvent.SystemEventType.ToString(), "", systemEvent.EventData);
59 | LockSlim.EnterWriteLock();
60 | SystemEventSamplesData.Add(hdf5SystemEvent);
61 | LockSlim.ExitWriteLock();
62 | }
63 | }
64 |
65 |
66 | public Task WaitForDataWritten()
67 | {
68 | try
69 | {
70 |
71 | record = false;
72 | LockSlim.EnterWriteLock();
73 | if (!SystemEventSamplesData.Any())
74 | {
75 |
76 | Logger.LogWarning("No system events to write to H5 file");
77 | return Task.CompletedTask;
78 | }
79 |
80 | var dataToWrite = SystemEventSamplesData;
81 | SystemEventSamplesData = new List();
82 | Logger.LogInformation("Start write of system events");
83 | Hdf5SystemEvents events = new Hdf5SystemEvents(dataToWrite);
84 | var status = Hdf5.WriteObject(GroupRoot, events, Constants.EventGroupName);
85 | Logger.LogInformation("End write of system events with status " + status);
86 | return Task.CompletedTask;
87 | }
88 | finally
89 | {
90 | LockSlim.ExitWriteLock();
91 |
92 |
93 | }
94 | }
95 |
96 | public void StopRecording() => record = false;
97 |
98 | public void StartLogging() => record = true;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/ECGData.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using HDF5CSharp.DataTypes;
4 |
5 | namespace HDF5CSharp.Example.DataTypes
6 | {
7 | public class ECGData : IEquatable
8 | {
9 |
10 | [Hdf5EntryName("start_datetime")] public DateTime StartDateTime { get; set; }
11 | [Hdf5EntryName("end_datetime")] public DateTime EndDateTime { get; set; }
12 | [Hdf5EntryName("sampling_rate")] public int SamplingRate { get; set; }
13 | [Hdf5EntryName("Signals_unfiltered")] public double[,] UnfilteredSignal { get; set; }
14 | [Hdf5EntryName("Signals_filtered")] public double[,] FilteredSignal { get; set; }
15 | [Hdf5EntryName("timestamps")] public long[,] Timestamps { get; set; }
16 | [Hdf5EntryName("packetids")] public long[,] PacketIds { get; set; }
17 | [Hdf5EntryName("kalpaclocks")] public long[,] KalpaClocks { get; set; }
18 |
19 | public ECGData()
20 | {
21 | Timestamps = new long[0, 0];
22 | FilteredSignal = new double[0, 0];
23 | UnfilteredSignal = new double[0, 0];
24 | PacketIds = new long[0, 0];
25 | KalpaClocks = new long[0, 0];
26 | }
27 |
28 | public bool Equals(ECGData other)
29 | {
30 | if (ReferenceEquals(null, other))
31 | {
32 | return false;
33 | }
34 |
35 | if (ReferenceEquals(this, other))
36 | {
37 | return true;
38 | }
39 |
40 | return StartDateTime.EqualsUpToMilliseconds(other.StartDateTime) &&
41 | EndDateTime.EqualsUpToMilliseconds(other.EndDateTime) &&
42 | SamplingRate == other.SamplingRate &&
43 |
44 |
45 | UnfilteredSignal.Rank == other.UnfilteredSignal.Rank &&
46 | Enumerable.Range(0, UnfilteredSignal.Rank).All(dimension =>
47 | UnfilteredSignal.GetLength(dimension) == other.UnfilteredSignal.GetLength(dimension)) &&
48 | UnfilteredSignal.Cast().SequenceEqual(other.UnfilteredSignal.Cast()) &&
49 |
50 | FilteredSignal.Rank == other.FilteredSignal.Rank &&
51 | Enumerable.Range(0, FilteredSignal.Rank).All(dimension =>
52 | FilteredSignal.GetLength(dimension) == other.FilteredSignal.GetLength(dimension)) &&
53 | FilteredSignal.Cast().SequenceEqual(other.FilteredSignal.Cast()) &&
54 | Timestamps.Rank == other.Timestamps.Rank &&
55 | Enumerable.Range(0, Timestamps.Rank).All(dimension =>
56 | Timestamps.GetLength(dimension) == other.Timestamps.GetLength(dimension)) &&
57 | Timestamps.Cast().SequenceEqual(other.Timestamps.Cast());
58 | }
59 |
60 | public override bool Equals(object obj)
61 | {
62 | if (ReferenceEquals(null, obj))
63 | {
64 | return false;
65 | }
66 |
67 | if (ReferenceEquals(this, obj))
68 | {
69 | return true;
70 | }
71 |
72 | if (obj.GetType() != this.GetType())
73 | {
74 | return false;
75 | }
76 |
77 | return Equals((ECGData)obj);
78 | }
79 |
80 | public override int GetHashCode()
81 | {
82 | return (StartDateTime.GetHashCode() * 397) ^ (EndDateTime.GetHashCode() * 397) ^ (SamplingRate * 397);
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/systemEvent.cs:
--------------------------------------------------------------------------------
1 | using HDF5CSharp.DataTypes;
2 | using System;
3 | using System.Runtime.InteropServices;
4 |
5 | namespace HDF5CSharp.Example.DataTypes
6 | {
7 | public enum SystemEventType
8 | {
9 | NewV2RModelReady = 0,
10 | NewMeshReady = 1,
11 | Saturation = 2,
12 | MissAlignment = 3,
13 | PAQConnectionError = 4,
14 | PAQConnectionOk = 5,
15 | PAQHardwareConnectionError = 6,
16 | PAQHardwareConnectionOk = 7,
17 | Dummy = 8,
18 | ECGCycleDescription = 9,
19 | SheathDetected = 10,
20 | LeakAnalysis = 11,
21 | NetworkAvailabilityOn,
22 | NetworkAvailabilityOff,
23 | ECGBodyLeadConnected,
24 | ECGBodyLeadDisconnected,
25 | FreeSpace
26 | }
27 |
28 | public class SystemEventModel : IEquatable
29 | {
30 | public SystemEventType SystemEventType { get; set; }
31 | public long TimeStamp { get; set; }
32 | public string EventData { get; set; }
33 |
34 | public SystemEventModel()
35 | {
36 | EventData = string.Empty;
37 | }
38 |
39 | public SystemEventModel(SystemEventType systemEventType, long timeStamp, string eventData)
40 | {
41 | SystemEventType = systemEventType;
42 | TimeStamp = timeStamp;
43 | EventData = eventData;
44 | }
45 |
46 | public bool Equals(SystemEventModel other)
47 | {
48 | if (ReferenceEquals(null, other))
49 | {
50 | return false;
51 | }
52 |
53 | if (ReferenceEquals(this, other))
54 | {
55 | return true;
56 | }
57 |
58 | return SystemEventType == other.SystemEventType && TimeStamp == other.TimeStamp && EventData == other.EventData;
59 | }
60 |
61 | public override bool Equals(object obj)
62 | {
63 | if (ReferenceEquals(null, obj))
64 | {
65 | return false;
66 | }
67 |
68 | if (ReferenceEquals(this, obj))
69 | {
70 | return true;
71 | }
72 |
73 | if (obj.GetType() != GetType())
74 | {
75 | return false;
76 | }
77 |
78 | return Equals((SystemEvent)obj);
79 | }
80 |
81 | public override int GetHashCode()
82 | {
83 | unchecked
84 | {
85 | var hashCode = (int)SystemEventType;
86 | hashCode = (hashCode * 397) ^ TimeStamp.GetHashCode();
87 | hashCode = (hashCode * 397) ^ (EventData != null ? EventData.GetHashCode() : 0);
88 | return hashCode;
89 | }
90 | }
91 | }
92 |
93 | [StructLayout(LayoutKind.Sequential)]
94 | public struct SystemEvent
95 | {
96 | [Hdf5EntryName("timestamp")] public long timestamp;
97 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
98 | [Hdf5EntryName("type")] public string type;
99 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
100 | [Hdf5EntryName("description")] public string description;
101 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
102 | [Hdf5EntryName("data")] public string data;
103 | public SystemEvent(long timestamp, string type, string description, string data)
104 | {
105 | this.timestamp = timestamp;
106 | this.type = type;
107 | this.description = description;
108 | this.data = data;
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/HDF5-CSharp.UnitTests/Hdf5ObjectTests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.TestTools.UnitTesting;
2 | using System;
3 | using System.IO;
4 |
5 | namespace HDF5CSharp.UnitTests.Core
6 | {
7 | public partial class Hdf5UnitTests
8 | {
9 | [TestMethod]
10 | public void WriteAndReadObjectWithPropertiesTest()
11 | {
12 | string filename = Path.Combine(folder, "testObjects.H5");
13 | try
14 | {
15 | testClass.TestInteger = 2;
16 | testClass.TestDouble = 1.1;
17 | testClass.TestBoolean = true;
18 | testClass.TestString = "test string";
19 | // 31-Oct-2003, 18:00 is 731885.75 in matlab
20 | testClass.TestTime = new DateTime(2003, 10, 31, 18, 0, 0);
21 |
22 | var fileId = Hdf5.CreateFile(filename);
23 | Assert.IsTrue(fileId > 0);
24 |
25 | Hdf5.WriteObject(fileId, testClass, "objectWithProperties");
26 | Hdf5.CloseFile(fileId);
27 | }
28 | catch (Exception ex)
29 | {
30 | CreateExceptionAssert(ex);
31 | }
32 |
33 | try
34 | {
35 | var fileId = Hdf5.OpenFile(filename);
36 | Assert.IsTrue(fileId > 0);
37 |
38 | TestClass readObject = new TestClass();
39 | readObject = Hdf5.ReadObject(fileId, readObject, "objectWithProperties");
40 | Assert.IsTrue(testClass.Equals(readObject));
41 |
42 | readObject = Hdf5.ReadObject(fileId, "objectWithProperties");
43 | Assert.IsTrue(testClass.Equals(readObject));
44 |
45 | Assert.IsTrue(Hdf5.CloseFile(fileId) >= 0);
46 | }
47 | catch (Exception ex)
48 | {
49 | CreateExceptionAssert(ex);
50 | }
51 | }
52 |
53 | [TestMethod]
54 | public void WriteAndReadObjectWithPropertiesAndArrayPropertyTest()
55 | {
56 | try
57 | {
58 | testClassWithArrays.TestInteger = 2;
59 | testClassWithArrays.TestDouble = 1.1;
60 | testClassWithArrays.TestBoolean = true;
61 | testClassWithArrays.TestString = "test string";
62 | testClassWithArrays.TestDoubles = new[] { 1.1, 1.2, -1.1, -1.2 };
63 | testClassWithArrays.TestStrings = new[] { "one", "two", "three", "four" };
64 | testClassWithArrays.testDoublesField = new[] { 1.1, 1.2, -1.1, -1.2 };
65 | testClassWithArrays.testStringsField = new[] { "one", "two", "three", "four" };
66 | string filename = Path.Combine(folder, "testArrayObjects.H5");
67 |
68 | var fileId = Hdf5.CreateFile(filename);
69 | Assert.IsTrue(fileId >= 0);
70 |
71 | Hdf5.WriteObject(fileId, testClassWithArrays, "objectWithTwoArrays");
72 |
73 | TestClassWithArray readObject = new TestClassWithArray
74 | {
75 | TestStrings = new string[0],
76 | TestDoubles = null,
77 | TestDouble = double.NaN
78 | };
79 |
80 | readObject = Hdf5.ReadObject(fileId, readObject, "objectWithTwoArrays");
81 | Assert.IsTrue(testClassWithArrays.Equals(readObject));
82 |
83 | readObject = Hdf5.ReadObject(fileId, "objectWithTwoArrays");
84 | Assert.IsTrue(testClassWithArrays.Equals(readObject));
85 |
86 | Assert.IsTrue(Hdf5.CloseFile(fileId) >= 0);
87 | }
88 | catch (Exception ex)
89 | {
90 | CreateExceptionAssert(ex);
91 | }
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/HDF5-CSharp/HDF5-CSharp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | HDF5CSharp
6 | HDF5CSharp
7 | false
8 | false
9 | Hdf5DotNetTools.snk
10 | AnyCPU;x86;x64
11 | SciSharp.Keras.HDF5
12 | SciSharp STACK
13 |
14 | SciSharp.Keras.HDF5
15 | C# Wrapper for HDF.PInvoke Library
16 | Apache 2.0, SciSharp STACK @2021
17 | MIT
18 | https://github.com/SciSharp/HDF5-CSharp
19 | https://avatars3.githubusercontent.com/u/44989469?s=200&v=4
20 | https://github.com/SciSharp/HDF5-CSharp
21 | git
22 | Dependents on HDF.PInvoke.1.10.500
23 | true
24 | 1.1.10.500
25 | true
26 | false
27 | snupkg
28 |
29 | false
30 | true
31 |
32 |
33 |
34 | DEBUG;TRACE;TRACE,HDF5_VER1_10
35 |
36 |
37 |
38 | TRACE;TRACE,HDF5_VER1_10
39 |
40 |
41 |
42 | TRACE;TRACE,HDF5_VER1_10
43 |
44 |
45 |
46 | TRACE;TRACE,HDF5_VER1_10
47 |
48 |
49 |
50 | TRACE;TRACE,HDF5_VER1_10
51 |
52 |
53 |
54 | TRACE;TRACE,HDF5_VER1_10
55 |
56 |
57 |
58 |
59 |
60 | all
61 | runtime; build; native; contentfiles; analyzers; buildtransitive
62 |
63 |
64 | all
65 | runtime; build; native; contentfiles; analyzers; buildtransitive
66 |
67 |
68 |
69 |
70 |
71 |
72 | True
73 | True
74 | Resources.resx
75 |
76 |
77 |
78 |
79 |
80 | ResXFileCodeGenerator
81 | Resources.Designer.cs
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/RPositionGroup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 | using HDF5CSharp.DataTypes;
8 | using Microsoft.Extensions.Logging;
9 |
10 | namespace HDF5CSharp.Example.DataTypes
11 | {
12 | public class Hdf5RPositionEvents
13 | {
14 | [Hdf5EntryName("rposition_events")] public RPositionEvent[] Events { get; set; }
15 | public Hdf5RPositionEvents(List eventsData)
16 | {
17 | Events = eventsData.ToArray();
18 | }
19 |
20 | public Hdf5RPositionEvents()
21 | {
22 |
23 | }
24 | }
25 | public class RPositionGroup : Hdf5BaseFile, IDisposable
26 | {
27 | [Hdf5Save(Hdf5Save.DoNotSave)] private ReaderWriterLockSlim LockSlim { get; }
28 | [Hdf5Save(Hdf5Save.DoNotSave)] private List RPositionSamplesData { get; set; }
29 | [Hdf5Save(Hdf5Save.DoNotSave)] private bool record;
30 |
31 | public RPositionGroup(long fileId, long groupRoot, ILogger logger) : base(fileId, groupRoot, "events", logger)
32 | {
33 | RPositionSamplesData = new List();
34 | LockSlim = new ReaderWriterLockSlim();
35 | }
36 |
37 | public void Dispose()
38 | {
39 | try
40 | {
41 | if (!Disposed)
42 | {
43 | Hdf5.CloseGroup(GroupId);
44 | }
45 |
46 | }
47 | catch (Exception e)
48 | {
49 | Logger.LogError(e, $"Error closing RPosition group: {e.Message}");
50 | }
51 | }
52 |
53 |
54 | public void Enqueue(RPositionsMessagePack rPosition)
55 | {
56 |
57 | if (record)
58 | {
59 | var positions = rPosition.NavigationData.SelectMany(r =>
60 | r.Points.Select(p => new RPositionEvent(rPosition.Timestamp, r.Name, p.x, p.y, p.z, r.Trajectory.x, r.Trajectory.y, r.Trajectory.z))).ToList();
61 | try
62 | {
63 | LockSlim.EnterWriteLock();
64 | RPositionSamplesData.AddRange(positions);
65 | }
66 | catch (Exception e)
67 | {
68 | Logger.LogError(e, $"Error adding RPosition: {e.Message}");
69 | }
70 | finally
71 | {
72 | LockSlim.ExitWriteLock();
73 | }
74 |
75 | }
76 | }
77 |
78 |
79 | public Task WaitForDataWritten()
80 | {
81 | try
82 | {
83 | record = false;
84 | LockSlim.EnterWriteLock();
85 | if (!RPositionSamplesData.Any())
86 | {
87 | Logger.LogWarning("No R Position events to write to H5 file");
88 | return Task.CompletedTask;
89 | }
90 | var dataToWrite = RPositionSamplesData;
91 | RPositionSamplesData = new List();
92 | Logger.LogInformation("Start write of RPosition events");
93 | Hdf5RPositionEvents events = new Hdf5RPositionEvents(dataToWrite);
94 | var status = Hdf5.WriteObject(GroupRoot, events, Constants.EventGroupName);
95 | Logger.LogInformation("End write of RPosition with status " + status);
96 | }
97 | catch (Exception e)
98 | {
99 | Logger.LogError(e, $"Error writing RPosition Events: {e.Message}");
100 | }
101 | finally
102 | {
103 | LockSlim.ExitWriteLock();
104 | }
105 | return Task.CompletedTask;
106 | }
107 |
108 |
109 |
110 | public void StopRecording() => record = false;
111 |
112 | public void StartLogging() => record = true;
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/PatientsContainer.cs:
--------------------------------------------------------------------------------
1 | using HDF5CSharp.DataTypes;
2 | using Microsoft.Extensions.Logging;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 |
7 | namespace HDF5CSharp.Example.DataTypes
8 | {
9 | [Serializable]
10 | [Hdf5GroupName("patients")]
11 | public class PatientsContainer : Hdf5BaseFile, IDisposable, IEquatable
12 | {
13 | [Hdf5EntryName("ManyPatients")] public List Patients { get; set; }
14 | [Hdf5EntryName("ManyPatientsField")] public List PatientsField;
15 | public PatientsContainer()
16 | {
17 |
18 | }
19 | public PatientsContainer(long fileId, long groupRoot, ILogger logger) : base(fileId, groupRoot, "patients",
20 | logger)
21 | {
22 | Patients = new List();
23 | Patients.Add(new Patient[]
24 | {
25 | new Patient()
26 | {
27 | Age = 20, ExamDate = DateTime.Now.AddDays(-10), FirstName = "first1", Gender = "F", Height = 1.65,
28 | Id = "000", LastName = "last1", Weight = 60
29 | },
30 | new Patient()
31 | {
32 | Age = 20, ExamDate = DateTime.Now.AddDays(-10), FirstName = "first2", Gender = "M", Height = 1.85,
33 | Id = "111", LastName = "last2", Weight = 90
34 | },
35 | });
36 |
37 | PatientsField = new List();
38 | PatientsField.Add(new Patient[]
39 | {
40 | new Patient()
41 | {
42 | Age = 20, ExamDate = DateTime.Now.AddDays(-10), FirstName = "first1", Gender = "F", Height = 1.65,
43 | Id = "000", LastName = "last1", Weight = 60
44 | },
45 | new Patient()
46 | {
47 | Age = 20, ExamDate = DateTime.Now.AddDays(-10), FirstName = "first2", Gender = "M", Height = 1.85,
48 | Id = "111", LastName = "last2", Weight = 90
49 | },
50 | });
51 | }
52 |
53 | public void Dispose()
54 | {
55 | try
56 | {
57 | if (!Disposed)
58 | {
59 | Hdf5.CloseGroup(GroupId);
60 | Disposed = true;
61 | }
62 | }
63 | catch (Exception e)
64 | {
65 | Logger?.LogError($"Error closing file: {e}");
66 | }
67 |
68 | }
69 |
70 | public bool Equals(PatientsContainer other)
71 | {
72 | if (ReferenceEquals(null, other))
73 | {
74 | return false;
75 | }
76 |
77 | if (ReferenceEquals(this, other))
78 | {
79 | return true;
80 | }
81 |
82 | for (var i = 0; i < Patients.Count; i++)
83 | {
84 | var p = Patients[i];
85 | if (!p.SequenceEqual(other.Patients[i]))
86 | {
87 | return false;
88 | }
89 | }
90 | for (var i = 0; i < PatientsField.Count; i++)
91 | {
92 | var p = PatientsField[i];
93 | if (!p.SequenceEqual(other.PatientsField[i]))
94 | {
95 | return false;
96 | }
97 | }
98 | return true;
99 | }
100 |
101 | public override bool Equals(object obj)
102 | {
103 | if (ReferenceEquals(null, obj))
104 | {
105 | return false;
106 | }
107 |
108 | if (ReferenceEquals(this, obj))
109 | {
110 | return true;
111 | }
112 |
113 | if (obj.GetType() != this.GetType())
114 | {
115 | return false;
116 | }
117 |
118 | return Equals((PatientsContainer)obj);
119 | }
120 |
121 | public override int GetHashCode() => (Patients != null ? Patients.GetHashCode() : 0);
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/HDF5-CSharp.UnitTests/Hdf5StringsTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using Microsoft.VisualStudio.TestTools.UnitTesting;
6 |
7 | namespace HDF5CSharp.UnitTests.Core
8 | {
9 | public partial class Hdf5UnitTests
10 | {
11 |
12 | [TestMethod]
13 | public void WriteAndReadOneString()
14 | {
15 | try
16 | {
17 | string[] str = new[] { "test" };
18 |
19 | string filename = Path.Combine(folder, "testOneStringList.H5");
20 |
21 |
22 | // Open file and write the strings
23 | var fileId = Hdf5.CreateFile(filename);
24 | Assert.IsTrue(fileId > 0);
25 | Hdf5.WriteStrings(fileId, "/test", str);
26 |
27 | // Read the strings and close file
28 | Assert.IsTrue(fileId > 0);
29 | IEnumerable strs2 = Hdf5.ReadStrings(fileId, "/test", "").result;
30 | Assert.IsTrue(strs2.Count() == 1);
31 | foreach (var s in strs2)
32 | {
33 | Assert.IsTrue(str[0] == s);
34 | };
35 |
36 | Hdf5.CloseFile(fileId);
37 | }
38 | catch (Exception ex)
39 | {
40 | CreateExceptionAssert(ex);
41 | }
42 | }
43 |
44 | [TestMethod]
45 | public void WriteAndReadListOfStrings()
46 | {
47 | try
48 | {
49 | List strs = new List
50 | {
51 | "t",
52 | "tst",
53 | "test1",
54 | "small test"
55 | };
56 |
57 | string filename = Path.Combine(folder, "testStringList.H5");
58 |
59 |
60 | // Open file and write the strings
61 | var fileId = Hdf5.CreateFile(filename);
62 | Assert.IsTrue(fileId > 0);
63 | Hdf5.WriteStrings(fileId, "/test", strs);
64 |
65 | // Read the strings and close file
66 | Assert.IsTrue(fileId > 0);
67 | IEnumerable strs2 = Hdf5.ReadStrings(fileId, "/test", "").result;
68 | Assert.IsTrue(strs.Count() == strs2.Count());
69 | foreach (var item in strs2.Select((str, i) => new { i, str }))
70 | {
71 | Assert.IsTrue(item.str == strs[item.i]);
72 | }
73 |
74 | Hdf5.CloseFile(fileId);
75 | }
76 | catch (Exception ex)
77 | {
78 | CreateExceptionAssert(ex);
79 | }
80 | }
81 |
82 | [TestMethod]
83 | public void WriteAndReadOneAsciiString()
84 | {
85 | try
86 | {
87 | string test = "This is a test string";
88 | string filename = Path.Combine(folder, "testOneString.H5");
89 |
90 |
91 | var fileId = Hdf5.CreateFile(filename);
92 | Hdf5.WriteAsciiString(fileId, "/test", test);
93 | Assert.IsTrue(Hdf5.CloseFile(fileId) == 0);
94 |
95 | fileId = Hdf5.OpenFile(filename);
96 | string readStr = Hdf5.ReadAsciiString(fileId, "/test");
97 | Assert.IsTrue(test == readStr);
98 | Assert.IsTrue(Hdf5.CloseFile(fileId) == 0);
99 | }
100 | catch (Exception ex)
101 | {
102 | CreateExceptionAssert(ex);
103 | }
104 | }
105 |
106 | [TestMethod]
107 | public void WriteAndReadOneUnicodeString()
108 | {
109 | try
110 | {
111 | string test = "Γαζέες καὶ μυρτιὲς δὲν θὰ βρῶ πιὰ στὸ χρυσαφὶ ξέφωτο";
112 | string filename = Path.Combine(folder, "testUnicodeString.H5");
113 |
114 |
115 | var fileId = Hdf5.CreateFile(filename);
116 | Hdf5.WriteUnicodeString(fileId, "/test", test);
117 | Assert.IsTrue(Hdf5.CloseFile(fileId) >= 0);
118 |
119 |
120 | fileId = Hdf5.OpenFile(filename);
121 | string readStr = Hdf5.ReadUnicodeString(fileId, "/test");
122 | //var readStr = Hdf5.ReadStrings(fileId, "/test");
123 | Assert.IsTrue(test == readStr);
124 | Assert.IsTrue(Hdf5.CloseFile(fileId) >= 0);
125 | }
126 | catch (Exception ex)
127 | {
128 | CreateExceptionAssert(ex);
129 | }
130 | }
131 |
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/ECGCycleDescription.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.Runtime.CompilerServices;
4 |
5 | namespace HDF5CSharp.Example.DataTypes
6 | {
7 | [Serializable]
8 | public struct ECGCycleDescription
9 | {
10 | //QRS
11 | public double StartOfQRSAmplitude;//QRS onset amplitude
12 | public double EndOfQRSAmplitude; //QRS offset amplitude
13 | public double RPeakAmplitude; //R-Peak amplitude
14 | //P-Peak
15 | public double StartOfPWaveAmplitude;//P-wave onset amplitude
16 | public double EndOfPWaveAmplitude; //P-wave offset amplitude
17 | public double PPeakAmplitude; //P-Peak amplitude
18 | //T-wave
19 | public double StartOfTWaveAmplitude;//T-wave onset amplitude
20 | public double EndOfTWaveAmplitude; //T-wave offset amplitude
21 | public double TPeakAmplitude; //T-Peak amplitude
22 | //Internal
23 | //A
24 | public byte IsAPeakExist;//0 - false; >0 - true
25 | public double APeakAmplitude;//A-peak amplitude [mkV]
26 | //V
27 | public byte IsVPeakExist;//0 - false; >0 - true
28 | public double VPeakAmplitude;//V-peak amplitude [mkV]
29 |
30 | public byte IsLumenMarkerExist; //0 - false; >0 - true
31 | public Int32 LumenPosition; //Lumen market position.
32 |
33 |
34 | public long TimestampStartOfQRSInterval;
35 | public long TimestampEndOfQRSInterval;
36 | public long TimestampRPeak;
37 | public long TimestampStartOfPWaveInterval;
38 | public long TimestampEndOfPWaveInterval;
39 | public long TimestampPPeak;
40 | public long TimestampAPeak;
41 | public long TimestampVPeak;
42 | public long TimestampTPeak;
43 | public long CurrentTimestamp;
44 |
45 |
46 | public ECGCycleDescription(ECGCycleDescription marshelledData, long currentTimestamp, double samplingRate, long currentIndex, int shiftBS, int shiftIC)
47 | {
48 | CurrentTimestamp = currentTimestamp;
49 | StartOfQRSAmplitude = marshelledData.StartOfQRSAmplitude;
50 | EndOfQRSAmplitude = marshelledData.EndOfQRSAmplitude;
51 | RPeakAmplitude = marshelledData.RPeakAmplitude;
52 | StartOfPWaveAmplitude = marshelledData.StartOfPWaveAmplitude;
53 | EndOfPWaveAmplitude = marshelledData.EndOfPWaveAmplitude;
54 | PPeakAmplitude = marshelledData.PPeakAmplitude;
55 | StartOfTWaveAmplitude = marshelledData.StartOfTWaveAmplitude;
56 | EndOfTWaveAmplitude = 0;
57 | TPeakAmplitude = marshelledData.TPeakAmplitude;
58 | IsAPeakExist = marshelledData.IsAPeakExist;
59 | APeakAmplitude = marshelledData.APeakAmplitude;
60 | IsVPeakExist = marshelledData.IsVPeakExist;
61 | VPeakAmplitude = marshelledData.VPeakAmplitude;
62 | TimestampStartOfQRSInterval = ConvertIndexToTimestamp(0, currentTimestamp, samplingRate, currentIndex, shiftBS);
63 | TimestampEndOfQRSInterval = ConvertIndexToTimestamp(0, currentTimestamp, samplingRate, currentIndex, shiftBS);
64 | TimestampRPeak = ConvertIndexToTimestamp(0, currentTimestamp, samplingRate, currentIndex, shiftBS);
65 | TimestampStartOfPWaveInterval = ConvertIndexToTimestamp(0, currentTimestamp, samplingRate, currentIndex, shiftBS);
66 | TimestampEndOfPWaveInterval = ConvertIndexToTimestamp(0, currentTimestamp, samplingRate, currentIndex, shiftBS);
67 | TimestampPPeak = ConvertIndexToTimestamp(0, currentTimestamp, samplingRate, currentIndex, shiftBS);
68 | TimestampAPeak = ConvertIndexToTimestamp(0, currentTimestamp, samplingRate, currentIndex, shiftIC);
69 | TimestampVPeak = ConvertIndexToTimestamp(0, currentTimestamp, samplingRate, currentIndex, shiftIC);
70 | //todo: check calculation
71 | TimestampTPeak = ConvertIndexToTimestamp(0, currentTimestamp, samplingRate, currentIndex, shiftIC);
72 | IsLumenMarkerExist = marshelledData.IsLumenMarkerExist;
73 | LumenPosition = marshelledData.LumenPosition;
74 | }
75 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
76 | private static long ConvertIndexToTimestamp(int relevantIndex, long currentTimestamp, double samplingRate, long currentIndex, int shift)
77 | {
78 | return (long)(currentTimestamp - (currentIndex - relevantIndex - shift) * samplingRate);
79 | }
80 |
81 | public string AsJson() => JsonConvert.SerializeObject(this);
82 | public static ECGCycleDescription FromJson(string jsonData) => JsonConvert.DeserializeObject(jsonData);
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Viewer/HDF5-CSharp.Viewer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {47201833-E346-46E1-B3F3-3B137B8BEB0D}
8 | WinExe
9 | Hdf5DotnetWrapper.Viewer
10 | Hdf5DotnetWrapper.Viewer
11 | v4.7.2
12 | 512
13 | true
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 | false
26 |
27 |
28 | AnyCPU
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | Form
52 |
53 |
54 | Form1.cs
55 |
56 |
57 | UserControl
58 |
59 |
60 | HDF5FileLoader.cs
61 |
62 |
63 |
64 |
65 | Form1.cs
66 |
67 |
68 | HDF5FileLoader.cs
69 |
70 |
71 | ResXFileCodeGenerator
72 | Resources.Designer.cs
73 | Designer
74 |
75 |
76 | True
77 | Resources.resx
78 |
79 |
80 | SettingsSingleFileGenerator
81 | Settings.Designer.cs
82 |
83 |
84 | True
85 | Settings.settings
86 | True
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | {7e7b1235-2d9c-4696-9ffb-cf7e14c7202a}
95 | HDF5-CSharp
96 |
97 |
98 |
99 |
100 | 1.10.610
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/HDF5-CSharp/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | text/microsoft-resx
91 |
92 |
93 | 1.3
94 |
95 |
96 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
97 |
98 |
99 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
100 |
101 |
--------------------------------------------------------------------------------
/HDF5-CSharp.UnitTests/TestUtilities.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 |
6 | namespace HDF5CSharp.UnitTests.Core
7 | {
8 | public static class UtilsExtensions
9 | {
10 | ///
11 | /// Compares each property of an object with the fields of another object to see if they are the same
12 | ///
13 | /// generic class type
14 | /// The object to compare
15 | /// The second object
16 | /// names of fields to ignore
17 | ///
18 | public static bool PublicInstancePropertiesEqual(this T self, T to, params string[] ignore) where T : class
19 | {
20 | var equal = false;
21 | if (self != null && to != null)
22 | {
23 | var type = typeof(T);
24 | var ignoreList = new List(ignore);
25 | var unequalProperties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance).
26 | Where(pi => !ignoreList.Contains(pi.Name));
27 | foreach (var pi in unequalProperties)
28 | {
29 | var selfValue = type.GetField(pi.Name).GetValue(self);
30 | var toValue = type.GetField(pi.Name).GetValue(to);
31 | Type selfType = selfValue.GetType();
32 | TypeCode code = Type.GetTypeCode(selfType);
33 | if (code == TypeCode.DateTime)
34 | {
35 | if (DateTime.Compare((DateTime)selfValue, (DateTime)toValue) != 0)
36 | {
37 | return false;
38 | }
39 | }
40 |
41 | if (selfType == typeof(TimeSpan))
42 | {
43 | if (TimeSpan.Compare((TimeSpan)selfValue, (TimeSpan)toValue) != 0)
44 | {
45 | return false;
46 | }
47 | }
48 |
49 | if (selfValue != toValue && (selfValue == null || !selfValue.Equals(toValue)))
50 | {
51 | return false;
52 | }
53 | }
54 | equal = true;
55 | }
56 | return equal;
57 | }
58 |
59 | ///
60 | /// Compares each field of an object with the fields of another object to see if they are the same
61 | ///
62 | /// generic class type
63 | /// The object to compare
64 | /// The second object
65 | /// names of fields to ignore
66 | ///
67 | public static bool PublicInstanceFieldsEqual(this T self, T to, params string[] ignore) where T : class
68 | {
69 | var equal = false;
70 | if (self != null && to != null)
71 | {
72 | var type = typeof(T);
73 | var ignoreList = new List(ignore);
74 | var unequalProperties = type.GetFields(BindingFlags.Public | BindingFlags.Instance).
75 | Where(pi => !ignoreList.Contains(pi.Name));
76 | foreach (var pi in unequalProperties)
77 | {
78 | var selfValue = type.GetField(pi.Name).GetValue(self);
79 | var toValue = type.GetField(pi.Name).GetValue(to);
80 | Type selfType = selfValue.GetType();
81 | TypeCode code = Type.GetTypeCode(selfType);
82 | if (code == TypeCode.DateTime)
83 | {
84 | if (DateTime.Compare((DateTime)selfValue, (DateTime)toValue) != 0)
85 | {
86 | return false;
87 | }
88 | }
89 |
90 | if (selfType == typeof(TimeSpan))
91 | {
92 | if (TimeSpan.Compare((TimeSpan)selfValue, (TimeSpan)toValue) != 0)
93 | {
94 | return false;
95 | }
96 | }
97 |
98 | if (selfValue != toValue && (!selfValue.Equals(toValue)))
99 | {
100 | return false;
101 | }
102 | }
103 | equal = true;
104 | }
105 | return equal;
106 | }
107 | }
108 | }
109 |
110 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Viewer/HDF5FileLoader.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace Hdf5DotnetWrapper.Viewer
2 | {
3 | partial class HDF5FileLoader
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Component Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.label18 = new System.Windows.Forms.Label();
32 | this.txtbHDF5 = new System.Windows.Forms.TextBox();
33 | this.btnHDF5ReadFile = new System.Windows.Forms.Button();
34 | this.btnHDF5Browse = new System.Windows.Forms.Button();
35 | this.SuspendLayout();
36 | //
37 | // label18
38 | //
39 | this.label18.AutoSize = true;
40 | this.label18.Location = new System.Drawing.Point(15, 8);
41 | this.label18.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
42 | this.label18.Name = "label18";
43 | this.label18.Size = new System.Drawing.Size(74, 18);
44 | this.label18.TabIndex = 10;
45 | this.label18.Text = "HDF5 File:";
46 | //
47 | // txtbHDF5
48 | //
49 | this.txtbHDF5.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
50 | | System.Windows.Forms.AnchorStyles.Right)));
51 | this.txtbHDF5.Location = new System.Drawing.Point(97, 4);
52 | this.txtbHDF5.Margin = new System.Windows.Forms.Padding(4);
53 | this.txtbHDF5.Name = "txtbHDF5";
54 | this.txtbHDF5.Size = new System.Drawing.Size(539, 26);
55 | this.txtbHDF5.TabIndex = 11;
56 | this.txtbHDF5.Text = "D:\\Data\\9_pig.h5";
57 | //
58 | // btnHDF5ReadFile
59 | //
60 | this.btnHDF5ReadFile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
61 | this.btnHDF5ReadFile.Location = new System.Drawing.Point(722, 1);
62 | this.btnHDF5ReadFile.Margin = new System.Windows.Forms.Padding(4);
63 | this.btnHDF5ReadFile.Name = "btnHDF5ReadFile";
64 | this.btnHDF5ReadFile.Size = new System.Drawing.Size(100, 32);
65 | this.btnHDF5ReadFile.TabIndex = 13;
66 | this.btnHDF5ReadFile.Text = "Load Data";
67 | this.btnHDF5ReadFile.UseVisualStyleBackColor = true;
68 | this.btnHDF5ReadFile.Click += new System.EventHandler(this.btnHDF5ReadFile_Click);
69 | //
70 | // btnHDF5Browse
71 | //
72 | this.btnHDF5Browse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
73 | this.btnHDF5Browse.Location = new System.Drawing.Point(644, 1);
74 | this.btnHDF5Browse.Margin = new System.Windows.Forms.Padding(4);
75 | this.btnHDF5Browse.Name = "btnHDF5Browse";
76 | this.btnHDF5Browse.Size = new System.Drawing.Size(69, 32);
77 | this.btnHDF5Browse.TabIndex = 12;
78 | this.btnHDF5Browse.Text = "Browse";
79 | this.btnHDF5Browse.UseVisualStyleBackColor = true;
80 | this.btnHDF5Browse.Click += new System.EventHandler(this.btnHDF5Browse_Click);
81 | //
82 | // HDF5FileLoader
83 | //
84 | this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 18F);
85 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
86 | this.Controls.Add(this.label18);
87 | this.Controls.Add(this.txtbHDF5);
88 | this.Controls.Add(this.btnHDF5ReadFile);
89 | this.Controls.Add(this.btnHDF5Browse);
90 | this.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
91 | this.Name = "HDF5FileLoader";
92 | this.Size = new System.Drawing.Size(826, 550);
93 | this.ResumeLayout(false);
94 | this.PerformLayout();
95 |
96 | }
97 |
98 | #endregion
99 |
100 | private System.Windows.Forms.Label label18;
101 | private System.Windows.Forms.TextBox txtbHDF5;
102 | private System.Windows.Forms.Button btnHDF5ReadFile;
103 | private System.Windows.Forms.Button btnHDF5Browse;
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/HDF5-CSharp.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29519.87
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HDF5-CSharp", "HDF5-CSharp\HDF5-CSharp.csproj", "{7E7B1235-2D9C-4696-9FFB-CF7E14C7202A}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HDF5-CSharp.Example", "HDF5-CSharp.Example\HDF5-CSharp.Example.csproj", "{5555E266-9088-4DC1-B281-F7E859CDC412}"
9 | EndProject
10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HDF5-CSharp.Example.UnitTest", "HDF5-CSharp.Example.UnitTest\HDF5-CSharp.Example.UnitTest.csproj", "{B773FD82-8EAF-4BA2-93BC-6B44AFDFDF8D}"
11 | EndProject
12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HDF5-CSharp.UnitTests", "HDF5-CSharp.UnitTests\HDF5-CSharp.UnitTests.csproj", "{D8396F76-47C8-4519-A288-4519A17C3620}"
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|Any CPU = Debug|Any CPU
17 | Debug|x64 = Debug|x64
18 | Debug|x86 = Debug|x86
19 | Release|Any CPU = Release|Any CPU
20 | Release|x64 = Release|x64
21 | Release|x86 = Release|x86
22 | EndGlobalSection
23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
24 | {7E7B1235-2D9C-4696-9FFB-CF7E14C7202A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {7E7B1235-2D9C-4696-9FFB-CF7E14C7202A}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {7E7B1235-2D9C-4696-9FFB-CF7E14C7202A}.Debug|x64.ActiveCfg = Debug|x64
27 | {7E7B1235-2D9C-4696-9FFB-CF7E14C7202A}.Debug|x64.Build.0 = Debug|x64
28 | {7E7B1235-2D9C-4696-9FFB-CF7E14C7202A}.Debug|x86.ActiveCfg = Debug|x86
29 | {7E7B1235-2D9C-4696-9FFB-CF7E14C7202A}.Debug|x86.Build.0 = Debug|x86
30 | {7E7B1235-2D9C-4696-9FFB-CF7E14C7202A}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {7E7B1235-2D9C-4696-9FFB-CF7E14C7202A}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {7E7B1235-2D9C-4696-9FFB-CF7E14C7202A}.Release|x64.ActiveCfg = Release|x64
33 | {7E7B1235-2D9C-4696-9FFB-CF7E14C7202A}.Release|x64.Build.0 = Release|x64
34 | {7E7B1235-2D9C-4696-9FFB-CF7E14C7202A}.Release|x86.ActiveCfg = Release|x86
35 | {7E7B1235-2D9C-4696-9FFB-CF7E14C7202A}.Release|x86.Build.0 = Release|x86
36 | {5555E266-9088-4DC1-B281-F7E859CDC412}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {5555E266-9088-4DC1-B281-F7E859CDC412}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {5555E266-9088-4DC1-B281-F7E859CDC412}.Debug|x64.ActiveCfg = Debug|Any CPU
39 | {5555E266-9088-4DC1-B281-F7E859CDC412}.Debug|x64.Build.0 = Debug|Any CPU
40 | {5555E266-9088-4DC1-B281-F7E859CDC412}.Debug|x86.ActiveCfg = Debug|Any CPU
41 | {5555E266-9088-4DC1-B281-F7E859CDC412}.Debug|x86.Build.0 = Debug|Any CPU
42 | {5555E266-9088-4DC1-B281-F7E859CDC412}.Release|Any CPU.ActiveCfg = Release|Any CPU
43 | {5555E266-9088-4DC1-B281-F7E859CDC412}.Release|Any CPU.Build.0 = Release|Any CPU
44 | {5555E266-9088-4DC1-B281-F7E859CDC412}.Release|x64.ActiveCfg = Release|Any CPU
45 | {5555E266-9088-4DC1-B281-F7E859CDC412}.Release|x64.Build.0 = Release|Any CPU
46 | {5555E266-9088-4DC1-B281-F7E859CDC412}.Release|x86.ActiveCfg = Release|Any CPU
47 | {5555E266-9088-4DC1-B281-F7E859CDC412}.Release|x86.Build.0 = Release|Any CPU
48 | {B773FD82-8EAF-4BA2-93BC-6B44AFDFDF8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
49 | {B773FD82-8EAF-4BA2-93BC-6B44AFDFDF8D}.Debug|Any CPU.Build.0 = Debug|Any CPU
50 | {B773FD82-8EAF-4BA2-93BC-6B44AFDFDF8D}.Debug|x64.ActiveCfg = Debug|Any CPU
51 | {B773FD82-8EAF-4BA2-93BC-6B44AFDFDF8D}.Debug|x64.Build.0 = Debug|Any CPU
52 | {B773FD82-8EAF-4BA2-93BC-6B44AFDFDF8D}.Debug|x86.ActiveCfg = Debug|Any CPU
53 | {B773FD82-8EAF-4BA2-93BC-6B44AFDFDF8D}.Debug|x86.Build.0 = Debug|Any CPU
54 | {B773FD82-8EAF-4BA2-93BC-6B44AFDFDF8D}.Release|Any CPU.ActiveCfg = Release|Any CPU
55 | {B773FD82-8EAF-4BA2-93BC-6B44AFDFDF8D}.Release|Any CPU.Build.0 = Release|Any CPU
56 | {B773FD82-8EAF-4BA2-93BC-6B44AFDFDF8D}.Release|x64.ActiveCfg = Release|Any CPU
57 | {B773FD82-8EAF-4BA2-93BC-6B44AFDFDF8D}.Release|x64.Build.0 = Release|Any CPU
58 | {B773FD82-8EAF-4BA2-93BC-6B44AFDFDF8D}.Release|x86.ActiveCfg = Release|Any CPU
59 | {B773FD82-8EAF-4BA2-93BC-6B44AFDFDF8D}.Release|x86.Build.0 = Release|Any CPU
60 | {D8396F76-47C8-4519-A288-4519A17C3620}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
61 | {D8396F76-47C8-4519-A288-4519A17C3620}.Debug|Any CPU.Build.0 = Debug|Any CPU
62 | {D8396F76-47C8-4519-A288-4519A17C3620}.Debug|x64.ActiveCfg = Debug|Any CPU
63 | {D8396F76-47C8-4519-A288-4519A17C3620}.Debug|x64.Build.0 = Debug|Any CPU
64 | {D8396F76-47C8-4519-A288-4519A17C3620}.Debug|x86.ActiveCfg = Debug|Any CPU
65 | {D8396F76-47C8-4519-A288-4519A17C3620}.Debug|x86.Build.0 = Debug|Any CPU
66 | {D8396F76-47C8-4519-A288-4519A17C3620}.Release|Any CPU.ActiveCfg = Release|Any CPU
67 | {D8396F76-47C8-4519-A288-4519A17C3620}.Release|Any CPU.Build.0 = Release|Any CPU
68 | {D8396F76-47C8-4519-A288-4519A17C3620}.Release|x64.ActiveCfg = Release|Any CPU
69 | {D8396F76-47C8-4519-A288-4519A17C3620}.Release|x64.Build.0 = Release|Any CPU
70 | {D8396F76-47C8-4519-A288-4519A17C3620}.Release|x86.ActiveCfg = Release|Any CPU
71 | {D8396F76-47C8-4519-A288-4519A17C3620}.Release|x86.Build.0 = Release|Any CPU
72 | EndGlobalSection
73 | GlobalSection(SolutionProperties) = preSolution
74 | HideSolutionNode = FALSE
75 | EndGlobalSection
76 | GlobalSection(ExtensibilityGlobals) = postSolution
77 | SolutionGuid = {FF170207-E294-49AB-96B4-37ACC61A6217}
78 | EndGlobalSection
79 | EndGlobal
80 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/KamaAcquisitionReadOnlyFile.cs:
--------------------------------------------------------------------------------
1 | using HDF5CSharp.Example.DataTypes;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 |
6 | namespace HDF5CSharp.Example
7 | {
8 | public class KamaAcquisitionReadOnlyFile : IDisposable
9 | {
10 | public string FileName { get; }
11 | public ProcedureInformation ProcedureInformation { get; set; }
12 | public SystemInformation SystemInformation { get; set; }
13 | public Patient PatientInformation { get; set; }
14 | public ECGData ECG { get; set; }
15 | public List EITs { get; set; }
16 | public List Events { get; set; }
17 | public bool HasEIT => EITs.Any();
18 | private long fileId;
19 | private string rootName = "/";
20 | private string rootNameOld = "/root";
21 | private string system_informationName = "/system_information";
22 | private string procedure_informationName = "/procedure_information";
23 | private string patient_informationName = "/patient";
24 | private string ecgName = "/ecg";
25 | private string eitName = "/eit";
26 | private string eventsName = "/events/system_events";
27 | private bool fileClosed;
28 |
29 | public KamaAcquisitionReadOnlyFile(string filename)
30 | {
31 | FileName = filename;
32 | ProcedureInformation = new ProcedureInformation();
33 | SystemInformation = new SystemInformation();
34 | PatientInformation = new Patient();
35 | ECG = new ECGData();
36 | EITs = new List();
37 | Events = new List();
38 | Hdf5.Settings.LowerCaseNaming = true;
39 | Hdf5.Settings.DateTimeType = DateTimeType.UnixTimeMilliseconds;
40 | fileId = Hdf5.OpenFile(filename);
41 | }
42 |
43 | public void ReadSystemInformation()
44 | {
45 | string groupName = rootName + system_informationName;
46 | if (Hdf5.GroupExists(fileId, groupName))
47 | {
48 | SystemInformation = Hdf5.ReadObject(fileId, groupName);
49 | return;
50 | }
51 | groupName = rootNameOld + system_informationName;
52 | if (Hdf5.GroupExists(fileId, groupName))
53 | {
54 | SystemInformation = Hdf5.ReadObject(fileId, groupName);
55 | }
56 | }
57 | public void ReadProcedureInformation()
58 | {
59 | string groupName = rootName + procedure_informationName;
60 | if (Hdf5.GroupExists(fileId, groupName))
61 | {
62 | ProcedureInformation = Hdf5.ReadObject(fileId, groupName);
63 | return;
64 | }
65 | groupName = rootNameOld + procedure_informationName;
66 | if (Hdf5.GroupExists(fileId, groupName))
67 | {
68 | ProcedureInformation = Hdf5.ReadObject(fileId, groupName);
69 | }
70 | }
71 | public void ReadPatientInformation()
72 | {
73 | string groupName = rootName + patient_informationName;
74 | if (Hdf5.GroupExists(fileId, groupName))
75 | {
76 | PatientInformation = Hdf5.ReadObject(fileId, groupName);
77 | return;
78 | }
79 | groupName = rootNameOld + patient_informationName;
80 | if (Hdf5.GroupExists(fileId, groupName))
81 | {
82 | PatientInformation = Hdf5.ReadObject(fileId, groupName);
83 | }
84 | }
85 |
86 | public void ReadECGData()
87 | {
88 | string groupName = rootName + ecgName;
89 | if (Hdf5.GroupExists(fileId, groupName))
90 | {
91 | ECG = Hdf5.ReadObject(fileId, groupName);
92 | return;
93 | }
94 | groupName = rootNameOld + ecgName;
95 | if (Hdf5.GroupExists(fileId, groupName))
96 | {
97 | ECG = Hdf5.ReadObject(fileId, groupName);
98 | }
99 | }
100 | public void ReadEITData()
101 | {
102 |
103 | int index = 1;
104 | string rootGroup = rootName + eitName;
105 | if (!Hdf5.GroupExists(fileId, rootGroup))
106 | {
107 | rootGroup = rootNameOld + eitName;
108 | }
109 |
110 | while (Hdf5.GroupExists(fileId, rootGroup + "/d" + index))
111 | {
112 | var entry = Hdf5.ReadObject(fileId, rootGroup + "/d" + index);
113 | EITs.Add(entry);
114 | index++;
115 | }
116 | }
117 |
118 | public void ReadSystemEvents()
119 | {
120 | string groupName = rootName + eventsName;
121 | if (Hdf5.GroupExists(fileId, groupName))
122 | {
123 | var e = Hdf5.ReadCompounds(fileId, groupName, "");
124 | Events.AddRange(e);
125 | }
126 |
127 |
128 | }
129 |
130 | public void Dispose()
131 | {
132 | if (!fileClosed)
133 | {
134 | Hdf5.CloseFile(fileId);
135 | fileClosed = true;
136 | }
137 | }
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/SystemInformation.cs:
--------------------------------------------------------------------------------
1 | using HDF5CSharp.DataTypes;
2 | using Microsoft.Extensions.Logging;
3 | using System;
4 | using System.Linq;
5 | using System.Net;
6 | using System.Net.NetworkInformation;
7 | using System.Net.Sockets;
8 | using System.Reflection;
9 |
10 | namespace HDF5CSharp.Example.DataTypes
11 | {
12 | [Hdf5GroupName("system_information")]
13 | public class SystemInformation : Hdf5BaseFile, IEquatable
14 | {
15 | [Hdf5EntryName("system_id")] public string SystemId { get; set; }
16 | [Hdf5EntryName("boards_id")] public string[] BoardIds { get; set; }
17 | [Hdf5EntryName("data_format_version")] public string DataFormatVersion { get; set; }
18 | [Hdf5EntryName("software_version")] public string SoftwareVersion { get; set; }
19 | [Hdf5EntryName("hdf5_version")] public string H5Version { get; set; }
20 | [Hdf5EntryName("hostname")] public string MachineName { get; set; }
21 | [Hdf5EntryName("mac_address")] public string MacAddress { get; set; }
22 | [Hdf5EntryName("ip_address")] public string IPAddress { get; set; }
23 | [Hdf5EntryName("assemblies_information")] public AssemblyInformationRecord[] Assemblies { get; set; }
24 | [Hdf5EntryName("system_type")] public string SystemType { get; set; }
25 | public SystemInformation(long fileId, long groupRoot, ILogger logger) : base(fileId, groupRoot, "system_information", logger)
26 | {
27 | Assemblies = new AssemblyInformationRecord[0];
28 | SystemId = "N/A";
29 | BoardIds = new[] { "N/A", "N/A" };
30 | DataFormatVersion = "3.0"; //v3 - ecg format changes
31 | H5Version = "4.1"; //v4 - ecg format changes, V4.1: add System type
32 | SoftwareVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
33 | MachineName = Environment.MachineName;
34 | MacAddress = GetMacAddress();
35 | IPAddress = GetLocalIPAddress();
36 | SystemType = string.Empty;
37 | }
38 |
39 |
40 | public SystemInformation()
41 | {
42 | BoardIds = Array.Empty();
43 | }
44 |
45 | private static string GetLocalIPAddress()
46 | {
47 | try
48 | {
49 | var host = Dns.GetHostEntry(Dns.GetHostName());
50 | foreach (var ip in host.AddressList)
51 | {
52 | if (ip.AddressFamily == AddressFamily.InterNetwork)
53 | {
54 | return ip.ToString();
55 | }
56 | }
57 | }
58 | catch (Exception)
59 | {
60 | return "0.0.0.0";
61 | }
62 |
63 | return "0.0.0.0";
64 | }
65 |
66 | ///
67 | /// Finds the MAC address of the NIC with maximum speed.
68 | ///
69 | /// The MAC address.
70 | private string GetMacAddress()
71 | {
72 | const int MIN_MAC_ADDR_LENGTH = 12;
73 | string macAddress = string.Empty;
74 | long maxSpeed = -1;
75 |
76 | foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
77 | {
78 | string tempMac = nic.GetPhysicalAddress().ToString();
79 | if (nic.Speed > maxSpeed &&
80 | !string.IsNullOrEmpty(tempMac) &&
81 | tempMac.Length >= MIN_MAC_ADDR_LENGTH)
82 | {
83 | maxSpeed = nic.Speed;
84 | macAddress = tempMac;
85 | }
86 | }
87 |
88 | return macAddress;
89 | }
90 |
91 | public bool Equals(SystemInformation other)
92 | {
93 | if (ReferenceEquals(null, other))
94 | {
95 | return false;
96 | }
97 |
98 | if (ReferenceEquals(this, other))
99 | {
100 | return true;
101 | }
102 |
103 | return SystemId == other.SystemId && BoardIds.SequenceEqual(other.BoardIds) &&
104 | DataFormatVersion == other.DataFormatVersion && SoftwareVersion == other.SoftwareVersion &&
105 | MachineName == other.MachineName && MacAddress == other.MacAddress && IPAddress == other.IPAddress &&
106 | SystemType == other.SystemType;
107 |
108 | }
109 |
110 | public override bool Equals(object obj)
111 | {
112 | if (ReferenceEquals(null, obj))
113 | {
114 | return false;
115 | }
116 |
117 | if (ReferenceEquals(this, obj))
118 | {
119 | return true;
120 | }
121 |
122 | if (obj.GetType() != this.GetType())
123 | {
124 | return false;
125 | }
126 |
127 | return Equals((SystemInformation)obj);
128 | }
129 |
130 | public override int GetHashCode()
131 | {
132 |
133 | return (SystemId.GetHashCode() * 397) ^ (DataFormatVersion.GetHashCode() * 397) ^
134 | (SoftwareVersion.GetHashCode() * 397) ^ (MachineName.GetHashCode() * 397) ^
135 | (MacAddress.GetHashCode() * 397) ^ (IPAddress.GetHashCode() * 397);
136 | }
137 |
138 | public override string ToString() => $"{nameof(SystemId)}: {SystemId}, {nameof(DataFormatVersion)}: {DataFormatVersion}, {nameof(SoftwareVersion)}: {SoftwareVersion}, {nameof(MachineName)}: {MachineName}, {nameof(MacAddress)}: {MacAddress}, {nameof(IPAddress)}: {IPAddress}. {nameof(SystemType)}: {SystemType}";
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/EITEntry.cs:
--------------------------------------------------------------------------------
1 | using HDF5CSharp.DataTypes;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 |
6 | namespace HDF5CSharp.Example.DataTypes
7 | {
8 | public class EITEntry : IEquatable
9 | {
10 | private IReadOnlyList _timestampsRaw;
11 | [Hdf5EntryName("configuration")] public string Configuration { get; set; }
12 | [Hdf5EntryName("start_datetime")] public DateTime StartDateTime { get; set; }
13 | [Hdf5EntryName("end_datetime")] public DateTime EndDateTime { get; set; }
14 | [Hdf5EntryName("voltages.re")] public float[,] VoltagesReal { get; set; }
15 | [Hdf5EntryName("voltages.im")] public float[,] VoltagesIm { get; set; }
16 | [Hdf5EntryName("currents.re")] public float[,] CurrentsReal { get; set; }
17 | [Hdf5EntryName("currents.im")] public float[,] CurrentsIm { get; set; }
18 | [Hdf5EntryName("saturations")] public ulong[,] Saturation { get; set; }
19 | [Hdf5EntryName("timestamps")] public long[,] Timestamps { get; set; }
20 | [Hdf5EntryName("packetids")] public ulong[,] PacketIds { get; set; }
21 | [Hdf5EntryName("kalpaclocks")] public ulong[,] KalpaClocks { get; set; }
22 |
23 | public EITEntry()
24 | {
25 | Configuration = string.Empty;
26 | _timestampsRaw = Array.Empty();
27 | }
28 |
29 | public bool Equals(EITEntry other)
30 | {
31 | if (ReferenceEquals(null, other))
32 | {
33 | return false;
34 | }
35 |
36 | if (ReferenceEquals(this, other))
37 | {
38 | return true;
39 | }
40 |
41 | var equal = Configuration == other.Configuration &&
42 | StartDateTime.EqualsUpToMilliseconds(other.StartDateTime) &&
43 | EndDateTime.EqualsUpToMilliseconds(other.EndDateTime) &&
44 |
45 | VoltagesReal.Rank == other.VoltagesReal.Rank &&
46 | Enumerable.Range(0, VoltagesReal.Rank).All(dimension =>
47 | VoltagesReal.GetLength(dimension) == other.VoltagesReal.GetLength(dimension)) &&
48 | VoltagesReal.Cast().SequenceEqual(other.VoltagesReal.Cast()) &&
49 |
50 | VoltagesIm.Rank == other.VoltagesIm.Rank &&
51 | Enumerable.Range(0, VoltagesIm.Rank).All(dimension =>
52 | VoltagesIm.GetLength(dimension) == other.VoltagesIm.GetLength(dimension)) &&
53 | VoltagesIm.Cast().SequenceEqual(other.VoltagesIm.Cast()) &&
54 |
55 | CurrentsReal.Rank == other.CurrentsReal.Rank &&
56 | Enumerable.Range(0, VoltagesIm.Rank).All(dimension =>
57 | CurrentsReal.GetLength(dimension) == other.CurrentsReal.GetLength(dimension)) &&
58 | CurrentsReal.Cast().SequenceEqual(other.CurrentsReal.Cast()) &&
59 |
60 | CurrentsIm.Rank == other.CurrentsIm.Rank &&
61 | Enumerable.Range(0, CurrentsIm.Rank).All(dimension =>
62 | CurrentsIm.GetLength(dimension) == other.CurrentsIm.GetLength(dimension)) &&
63 | CurrentsIm.Cast().SequenceEqual(other.CurrentsIm.Cast()) &&
64 |
65 | Saturation.Rank == other.Saturation.Rank &&
66 | Enumerable.Range(0, Saturation.Rank).All(dimension =>
67 | Saturation.GetLength(dimension) == other.Saturation.GetLength(dimension)) &&
68 | Saturation.Cast().SequenceEqual(other.Saturation.Cast()) &&
69 |
70 |
71 | Timestamps.Rank == other.Timestamps.Rank &&
72 | Enumerable.Range(0, Timestamps.Rank).All(dimension =>
73 | Timestamps.GetLength(dimension) == other.Timestamps.GetLength(dimension)) &&
74 | Timestamps.Cast().SequenceEqual(other.Timestamps.Cast());
75 |
76 | if (PacketIds != null && other.PacketIds != null)
77 | {
78 | equal = equal && PacketIds.Rank == other.PacketIds.Rank &&
79 | Enumerable.Range(0, PacketIds.Rank).All(dimension =>
80 | PacketIds.GetLength(dimension) == other.PacketIds.GetLength(dimension)) &&
81 | PacketIds.Cast().SequenceEqual(other.PacketIds.Cast());
82 | }
83 | if (KalpaClocks != null && other.KalpaClocks != null)
84 | {
85 | equal = equal && KalpaClocks.Rank == other.KalpaClocks.Rank &&
86 | Enumerable.Range(0, KalpaClocks.Rank).All(dimension =>
87 | KalpaClocks.GetLength(dimension) == other.KalpaClocks.GetLength(dimension)) &&
88 | KalpaClocks.Cast().SequenceEqual(other.KalpaClocks.Cast());
89 |
90 | }
91 | return equal;
92 | }
93 |
94 | public override bool Equals(object obj)
95 | {
96 | if (ReferenceEquals(null, obj))
97 | {
98 | return false;
99 | }
100 |
101 | if (ReferenceEquals(this, obj))
102 | {
103 | return true;
104 | }
105 |
106 | if (obj.GetType() != this.GetType())
107 | {
108 | return false;
109 | }
110 |
111 | return Equals((EITEntry)obj);
112 | }
113 |
114 | public override int GetHashCode()
115 | {
116 | return (Configuration.GetHashCode() * 397) ^ (StartDateTime.GetHashCode() * 397) ^
117 | (EndDateTime.GetHashCode() * 397);
118 | }
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Viewer/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/HDF5-CSharp/Hdf5AcquisitionWriter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using HDF.PInvoke;
7 | using HDF5CSharp.DataTypes;
8 |
9 | namespace HDF5CSharp
10 | {
11 |
12 |
13 | public class Hdf5AcquisitionFileWriter : IDisposable
14 | {
15 | long fileId;
16 | readonly string _groupName, _filename;
17 | ChunkedDataset dset;
18 | ulong _nrOfRecords, _sampleCount;
19 | long _groupId;
20 |
21 | // private readonly ReaderWriterLockSlim lock_ = new ReaderWriterLockSlim();
22 |
23 | public Hdf5AcquisitionFileWriter(string filename, string groupName = "ROOT")
24 | {
25 | H5E.set_auto(H5E.DEFAULT, null, IntPtr.Zero);
26 | //lock_.EnterWriteLock();
27 | _filename = filename;
28 | fileId = Hdf5.CreateFile(filename);
29 | _groupName = groupName;
30 | _groupId = Hdf5.CreateOrOpenGroup(fileId, Hdf5Utils.NormalizedName(_groupName));
31 |
32 | Header = new Hdf5AcquisitionFile();
33 | _nrOfRecords = 0;
34 | _sampleCount = 0;
35 | //lock_.ExitWriteLock();
36 |
37 | }
38 |
39 | public void Dispose()
40 | {
41 | Dispose(true);
42 | GC.SuppressFinalize(this);
43 | FileClosed?.Invoke(this, new FileClosedArgs(_filename));
44 | }
45 |
46 | protected virtual void Dispose(bool disposing)
47 | {
48 | if (disposing)
49 | {
50 | SaveHeader();
51 | dset?.Dispose();
52 | _groupId = Hdf5.CloseGroup(_groupId);
53 | fileId = Hdf5.CloseFile(fileId);
54 | }
55 | }
56 |
57 | public void SaveHeader()
58 | {
59 | //lock_.EnterWriteLock();
60 | Trace.WriteLine($"saving file {Header.Patient.Name} samples: {_sampleCount}; fileId: {fileId}");
61 | Header.Recording.EndTime = Header.Recording.StartTime + TimeSpan.FromSeconds(_sampleCount / Header.Recording.SampleRate);
62 | Header.Recording.NrOfSamples = _sampleCount;
63 | Header.EventListToEvents();
64 | for (int i = 0; i < Header.Channels.Count(); i++)
65 | {
66 | Header.Channels[i].NrOfSamples = _sampleCount;
67 | }
68 | Trace.WriteLine($"writing file {Header.Patient.Name} groupId: {_groupId}; fileId: {fileId}");
69 | Hdf5.WriteObject(_groupId, Header);
70 | //lock_.ExitWriteLock();
71 | }
72 |
73 | ///
74 | /// Writes data to the hdf5 file.
75 | ///
76 | public void Write(IEnumerable signals)
77 | {
78 | //lock_.EnterWriteLock();
79 | int cols = signals.Count();
80 | if (cols == 0)
81 | {
82 | return;
83 | }
84 |
85 | int rows = signals.First().Length;
86 | if (rows == 0)
87 | {
88 | return;
89 | }
90 | //double sr = _header.Recording.SampleRate;
91 |
92 | var data = new short[rows, cols];
93 | //var byteLength = rows * sizeof(short);
94 | int i = 0;
95 | foreach (var sig in signals)
96 | {
97 | for (int j = 0; j < rows; j++)
98 | {
99 | data[j, i] = Convert2Short(sig[j], i);
100 | }
101 |
102 | i++;
103 | }
104 | Write(data);
105 | //lock_.ExitWriteLock();
106 | }
107 |
108 | ///
109 | /// Writes data asynchronously to the hdf5 file.
110 | ///
111 | public async void WriteAsync(IEnumerable signals)
112 | {
113 | Task writeTask = new Task(() => Write(signals));
114 | writeTask.Start();
115 | await writeTask;
116 | }
117 |
118 | ///
119 | /// Writes data to the hdf5 file.
120 | ///
121 | public void Write(short[,] data)
122 | {
123 | //lock_.EnterWriteLock();
124 | if (_nrOfRecords == 0)
125 | {
126 | Header.Recording.StartTime = DateTime.Now;
127 | var dataName = "Data";
128 | dset = new ChunkedDataset(dataName, _groupId, data);
129 | }
130 | else
131 | {
132 | dset.AppendDataset(data);
133 | }
134 |
135 | _sampleCount += (ulong)data.GetLongLength(0);
136 | _nrOfRecords++;
137 | //lock_.ExitWriteLock();
138 | }
139 |
140 | ///
141 | /// Writes data asynchronously to the hdf5 file.
142 | ///
143 | public async void WriteAsync(short[,] data)
144 | {
145 | Task writeTask = new Task(() => Write(data));
146 | writeTask.Start();
147 | await writeTask;
148 | }
149 |
150 | public short Convert2Short(double val, int channelNr)
151 | {
152 | val = (val - Header.Channels[channelNr].Offset) / Header.Channels[channelNr].Amplification;
153 | //val = val * short.MaxValue;
154 | if (val > short.MaxValue)
155 | {
156 | val = short.MaxValue;
157 | }
158 |
159 | if (val < short.MinValue)
160 | {
161 | val = short.MinValue;
162 | }
163 |
164 | return Convert.ToInt16(Math.Round(val, MidpointRounding.AwayFromZero));
165 |
166 | }
167 |
168 | public Hdf5AcquisitionFile Header { get; }
169 |
170 | public event EventHandler FileClosed;
171 |
172 | }
173 |
174 |
175 | }
176 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Viewer/Form1.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Viewer/HDF5FileLoader.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/HDF5-CSharp.Example/DataTypes/RPositions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.CompilerServices;
6 | using System.Text;
7 | using MessagePack;
8 | using Newtonsoft.Json;
9 | using UnityEngine;
10 | namespace HDF5CSharp.Example.DataTypes
11 | {
12 | [Serializable]
13 | [MessagePackObject()]
14 | public class RPositionsMessagePack
15 | {
16 | [Key("timestamp")] public ulong Timestamp { get; set; }
17 | [Key("nav")] public List NavigationData { get; set; }
18 |
19 | public RPositionsMessagePack()
20 | {
21 | NavigationData = new List();
22 | }
23 |
24 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
25 | public static RPositionsMessagePack Deserialize(byte[] data)
26 | {
27 | try
28 | {
29 | return MessagePackSerializer.Deserialize(data);
30 | }
31 | catch (Exception e)
32 | {
33 | string path = $@"RPosition_Error_{DateTime.Now.Ticks}.bin";
34 | File.WriteAllBytes(path, data);
35 | var fallback = RPositionsOld.Deserialize(data);
36 | RPositionsMessagePack msg = new RPositionsMessagePack();
37 | msg.Timestamp = fallback.Timestamp;
38 | msg.NavigationData = new List(fallback.Data.Count);
39 | foreach (var rpos in fallback.Data)
40 | {
41 | msg.NavigationData.Add(new NavigationData { Name = rpos.Name, Points = rpos.Points.ToList() });
42 | }
43 | return msg;
44 | }
45 | }
46 |
47 | public void AddNavigationData(NavigationData navData) => NavigationData.Add(navData);
48 |
49 | public string ToJson() => JsonConvert.SerializeObject(this);
50 | }
51 | [Serializable]
52 | [MessagePackObject()]
53 | public class NavigationData
54 | {
55 | [Key("name")] public string Name { get; set; }
56 | [Key("position")] public List Points { get; set; }
57 | [Key("trajectory")] public Vector3 Trajectory { get; set; }
58 |
59 | public NavigationData()
60 | {
61 | Points = new List();
62 | }
63 |
64 | public void AddPoint(float x, float y, float z) => Points.Add(new Vector3(x, y, z));
65 | }
66 |
67 |
68 | [Serializable]
69 | [MessagePackObject(keyAsPropertyName: false)]
70 | internal class RPositionsOld
71 | {
72 | [Key("timestamp")] internal ulong Timestamp { get; set; }
73 |
74 | [Key("nav")] //keys are coming from Python code
75 | //public Dictionary Data { get; set; }
76 | internal List Data;
77 |
78 | [IgnoreMember] public DateTime Time => DateTime.FromBinary(Convert.ToInt64(Timestamp));
79 |
80 | //[IgnoreMember]
81 | //public string AsJson => JsonConvert.SerializeObject(this);
82 | internal static RPositionsOld Deserialize(byte[] data) =>
83 | TranslateDictionary(MessagePackSerializer.Deserialize>(data));
84 |
85 |
86 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
87 | private static RPositionsOld TranslateDictionary(Dictionary