I have raw ecg voltage samples in csv format e.g:
time voltage (mV)
0.000 9.169110459
0.001 9.144672532
0.002 9.144672532
0.003 9.169110459
0.004 9.169110459
0.005 9.169110459
0.006 9.169110459
0.007 9.144672532
0.008 9.217986315
0.009 9.169110459
0.01 9.169110459
0.011 9.169110459
0.012 9.169110459
0.013 9.144672532
0.014 9.144672532
0.015 9.169110459
0.016 9.169110459
0.017 9.169110459
0.018 9.169110459
0.019 9.169110459
0.02 9.169110459
0.021 9.169110459
0.022 9.144672532
0.023 9.169110459
and would like to convert this to a DICOM file, so that I can view it in an ecg viewer like ECG toolkit for c#: https://sourceforge.net/projects/ecgtoolkit-cs/
How would I go about this conversion? I have done some googling but haven't found a tool that is able to write dicom files from raw data.
EDIT:
I ended up going for an SCP file as this was easier. I ended up using the library above to create an scp file. Code below:
using System;
using System.Linq;
using ECGConversion;
using ECGConversion.ECGDemographics;
using ECGConversion.ECGSignals;
namespace SCPWriter
{
public static class CreateScpEcg
{
public static void CreateScpEcgFile(double[] voltages, int sampleRate, string directory, string patientId)
{
var rhythm = voltages;
var filePath = directory + patientId;
// get an empty ECG format file
IECGFormat format = ECGConverter.Instance.getFormat("SCP-ECG");
if (format != null)
{
// five required actions for the demographic info.
format.Demographics.Init();
format.Demographics.PatientID = patientId;
format.Demographics.LastName = "";
format.Demographics.TimeAcquisition = DateTime.Now;
// make an AcquiringDeviceID object
AcquiringDeviceID acqID = new AcquiringDeviceID(true);
// can also specify your own acquiring device info
Communication.IO.Tools.BytesTool.writeString("MYDEVI", acqID.ModelDescription, 0, acqID.ModelDescription.Length);
// set the Acquiring Device ID (required)
format.Demographics.AcqMachineID = acqID;
// declare the signal part.
var leadType = new LeadType[] { LeadType.I };
var rhythmAVM = 1;
var rhythmSPS = sampleRate;
Signals sigs = new Signals((byte)leadType.Length);
sigs.RhythmAVM = rhythmAVM;
sigs.RhythmSamplesPerSecond = rhythmSPS;
for (int i = 0; i < sigs.NrLeads; i++)
{
// very important to assign signal.
sigs[i] = new Signal();
sigs[i].Type = leadType[i];
sigs[i].Rhythm = rhythm.Select(Convert.ToInt16).ToArray();
sigs[i].RhythmStart = 0;
sigs[i].RhythmEnd = rhythm.Length - 1;
}
// store signal to the format.
if (format.Signals.setSignals(sigs) != 0)
{
Console.Error.WriteLine("setSignals failed!");
return;
}
// write the file
var outputFile = filePath + ".scp";
ECGWriter.Write(format, outputFile, true);
if (ECGWriter.getLastError() != 0)
{
Console.Error.WriteLine("Writing failed: {0}!", ECGWriter.getLastErrorMessage());
return;
}
}
}
}
}
NB: I was only interested in "lead I", but you can add more leads in this line: var leadType = new LeadType[] { LeadType.I }
NB: This is not my code, this is from one of the discussions in the sourceforge link above.
My recommendations:
Then it is pretty much straight forward. Walk through the mandatory attributes for the IOD you have chosen (one of the two I mentioned) and populate them by using the toolkit of your choice. Then use the toolkit to write the file to disk and you are done. Make sure to write the data as a DICOM File with a meta-header. A good toolkit provides that option upon writing datasets to disk.
Note that simply writing DICOM files to disk is not an "official DICOM interface". To exchange data between different DICOM applications, you either have to use network protocols (Storage Service Class in your case) or create DICOM conformant media (this puts some restrictions on media used, file formats, file names and requires to include a DICOM Directory file listing the contents of the media).
As you are asking for a tool, you might want to look at DCMTK. There are different ways to accomplish the task. dcmdump or dcmodify would be the tools to have a closer lookt at. However, it is cumbersome to do it this way and you will probably have to convert the ECG-data to a format that dcmtk can use to populate the waveform sequence. I am not advising you to go that way but it might be an approach to avoid writing a lot of code.