Click here to Skip to main content
15,885,078 members
Articles / Programming Languages / C#

Storing ECG to a PACS

Rate me:
Please Sign up or sign in to vote.
4.80/5 (10 votes)
16 Oct 2008Apache1 min read 107.1K   7.2K   48  
An article on a service that will store an ECG copied to a directory at a PACS. (supported formats SCP-ECG, DICOM-ECG and a recent version of HL7 aECG)
/***************************************************************************
Copyright 2008, Thoraxcentrum, Erasmus MC, Rotterdam, The Netherlands

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

	http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Written by Maarten JB van Ettinger.

****************************************************************************/
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.ServiceProcess;
using System.Threading;

using ECGConversion;
using ECGConversion.ECGManagementSystem;

namespace ECGtoPACS
{
	public class ECGtoPACS : System.ServiceProcess.ServiceBase
	{
		/// <summary> 
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;
		private System.IO.FileSystemWatcher _ECGWatcher;
		private String _FailDir;
		private String _SuccessDir;
		private Boolean _EraseOnSuccess;
		private ECGConfig _FormatConfig;
		private ECGConfig _SystemConfig;

		public ECGtoPACS()
		{
			// This call is required by the Windows.Forms Component Designer.
			InitializeComponent();

			_ECGWatcher.Created += new System.IO.FileSystemEventHandler(_ECGWatcher_Created);
		}

		// The main entry point for the process
		public static void Main(String[] args)
		{
			try
			{
				if ((args.Length == 1)
				&&	(String.Compare(args[0], "runcmd") == 0))
				{
					ECGtoPACS temp = new ECGtoPACS();

					temp.OnStart(null);
				
					while (true)
						Thread.Sleep(1000);
				}
				else
				{
					System.ServiceProcess.ServiceBase[] ServicesToRun;
	
					// More than one user Service may run within the same process. To add
					// another service to this process, change the following line to
					// create a second service object. For example,
					//
					//   ServicesToRun = new System.ServiceProcess.ServiceBase[] {new Service1(), new MySecondUserService()};
					//
					ServicesToRun = new System.ServiceProcess.ServiceBase[] { new ECGtoPACS() };

					System.ServiceProcess.ServiceBase.Run(ServicesToRun);
				}
			}
			catch (Exception ex)
			{
				ServiceLogger.Instance.Log(ex, EventLogEntryType.Error);
			}
		}

		/// <summary> 
		/// Required method for Designer support - do not modify 
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			_ECGWatcher = new System.IO.FileSystemWatcher();
			((System.ComponentModel.ISupportInitialize)(_ECGWatcher)).BeginInit();
			// 
			// newECGWatcher
			// 
			_ECGWatcher.EnableRaisingEvents = true;
			// 
			// ECGtoPACS
			// 
			this.ServiceName = "ECG to PACS";
			((System.ComponentModel.ISupportInitialize)(_ECGWatcher)).EndInit();
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		/// <summary>
		/// Set things in motion so your service can do its work.
		/// </summary>
		protected override void OnStart(String[] args)
		{
			if (args != null)
				ServiceLogger.Instance.EventLogger = this.EventLog;

			LoadConfig();

			if (Directory.Exists(_ECGWatcher.Path))
			{
				String[] files = Directory.GetFiles(_ECGWatcher.Path);

				if (files == null)
					return;

				foreach (String file in files)
					StoreECG(file);
			}
		}
 
		/// <summary>
		/// Stop this service.
		/// </summary>
		protected override void OnStop()
		{
			if (_ECGWatcher != null)
			{
				_ECGWatcher.Dispose();
				_ECGWatcher = null;
			}
		}

		/// <summary>
		/// Loading configuration
		/// </summary>
		private void LoadConfig()
		{
			_ECGWatcher.Path = System.Configuration.ConfigurationSettings.AppSettings["ImportDir"];
			_FailDir = Path.Combine(_ECGWatcher.Path, "failed");
			_SuccessDir = Path.Combine(_ECGWatcher.Path, "success");
			_EraseOnSuccess = String.Compare(System.Configuration.ConfigurationSettings.AppSettings["EraseOnSuccess"], "true", true) == 0;

			_FormatConfig = ECGConverter.Instance.getConfig("DICOM-ECG");

			IECGManagementSystem manSys = ECGConverter.Instance.getECGManagementSystem("PACS");
			_SystemConfig = manSys == null ? null : manSys.Config;

			LoadConfig(_FormatConfig);
			LoadConfig(_SystemConfig);
		}

		/// <summary>
		/// Loading config elements for an ECGConfig object.
		/// </summary>
		/// <param name="cfg">the ECGConfig object</param>
		private void LoadConfig(ECGConfig cfg)
		{
			if (cfg != null)
			{
				String name, val;
				bool must;

				for (int i=0,end = cfg.NrConfigItems;i < end;i++)
				{
					cfg.getConfigItem(i, out name, out must);

					val = System.Configuration.ConfigurationSettings.AppSettings[name];

					if (val != null)
						cfg[name] = val;
				}
			}
		}

		/// <summary>
		/// New file has been added to the 
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void _ECGWatcher_Created(object sender, System.IO.FileSystemEventArgs e)
		{
			StoreECG(e.FullPath);
		}

		private void StoreECG(String filePath)
		{
			if (System.IO.File.Exists(filePath))
			{
				bool bFail = false;

				try
				{
					UnknownECGReader reader = new UnknownECGReader();

					IECGFormat src = reader.Read(filePath);

					if ((reader.getError() == 0)
					&&	(src != null)
					&&	src.Works())
					{
						IECGManagementSystem pacs = ECGConverter.Instance.getECGManagementSystem("PACS");
						
						pacs.Config.Set(_SystemConfig);

						if (pacs.SaveECG(src, null, _FormatConfig) != 0)
						{
							ServiceLogger.Instance.Log("Storing ECG to PACS failed!", EventLogEntryType.FailureAudit);

							bFail = true;
						}
					}
					else
					{
						ServiceLogger.Instance.Log("Unknown ECG file type!", EventLogEntryType.FailureAudit);

						bFail = true;
					}
				}
				catch (Exception ex)
				{
					ServiceLogger.Instance.Log(ex, EventLogEntryType.Error);
					bFail = true;
				}

				if (bFail)
				{
					try
					{
						if (!Directory.Exists(_FailDir))
							Directory.CreateDirectory(_FailDir);

						String
							tempPath = Path.Combine(
							_FailDir,
							Path.GetFileName(filePath)),
							toPath = tempPath + ".0";

						for (int i=1;File.Exists(toPath);i++)
						{
							toPath = tempPath + "." + i.ToString();
						}

						File.Move(filePath, toPath);
					}
					catch (Exception ex)
					{
						ServiceLogger.Instance.Log(ex, EventLogEntryType.Error);
					}
				}
				else if (_EraseOnSuccess)
				{
					File.Delete(filePath);
				}
				else
				{
					if (!Directory.Exists(_SuccessDir))
						Directory.CreateDirectory(_SuccessDir);

					String
						tempPath = Path.Combine(
						_SuccessDir,
						Path.GetFileName(filePath)),
						toPath = tempPath + ".0";

					for (int i=1;File.Exists(toPath);i++)
					{
						toPath = tempPath + "." + i.ToString();
					}

					File.Move(filePath, toPath);
				}
			}
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Apache License, Version 2.0


Written By
Software Developer Erasmus MC
Netherlands Netherlands
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions