/trunk/EDFHeader.cs

# · C# · 408 lines · 350 code · 52 blank · 6 comment · 19 complexity · 067e9b8c930343e4802e39ffe06e433f MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. namespace EDF
  5. {
  6. public class EDFHeader
  7. {
  8. public static string EDFContinuous = "EDF+C";
  9. public static string EDFDiscontinuous = "EDF+D";
  10. private static string VERSION_DEFAULT = "0 ";
  11. private bool _isEDFPlus = false;
  12. public bool IsEDFPlus
  13. {
  14. get
  15. {
  16. return _isEDFPlus;
  17. }
  18. }
  19. public EDFHeader()
  20. {
  21. initializeEDFHeader();
  22. }
  23. public EDFHeader(bool isEDFPlus)
  24. {
  25. this._isEDFPlus = isEDFPlus;
  26. initializeEDFHeader();
  27. }
  28. public EDFHeader(char[] header)
  29. {
  30. if (header.Length != 256)
  31. {
  32. throw new ArgumentException("Header must be 256 characters");
  33. }
  34. parseHeader(header);
  35. }
  36. private void initializeEDFHeader()
  37. {
  38. this.Signals = new List<EDFSignal>();
  39. this.Version = string.Empty;
  40. this._PatientInformation = new EDFLocalPatientIdentification(getFixedLengthString(string.Empty, EDFHeader.FixedLength_LocalPatientIdentification).ToCharArray());
  41. this._RecordingInformation = new EDFLocalRecordingIdentification(getFixedLengthString(string.Empty, EDFHeader.FixedLength_LocalRecordingIdentifiaction).ToCharArray());
  42. this.StartDateEDF = DateTime.MinValue.ToString("dd.MM.yy");
  43. this.StartTimeEDF = DateTime.MinValue.ToString("hh.mm.ss");
  44. this.NumberOfBytes = 0;
  45. this.NumberOfDataRecords = 0;
  46. this.DurationOfDataRecordInSeconds = 0;
  47. this.NumberOfSignalsInDataRecord = this.Signals.Count;
  48. this.Reserved = string.Empty;
  49. }
  50. private static int FixedLength_Version = 8;
  51. private string _Version = VERSION_DEFAULT;
  52. public string Version
  53. {
  54. get
  55. {
  56. return _Version;
  57. }
  58. set
  59. {
  60. _Version = getFixedLengthString(value, FixedLength_Version);
  61. }
  62. }
  63. public static int FixedLength_LocalPatientIdentification = 80;
  64. private EDFLocalPatientIdentification _PatientInformation;
  65. public EDFLocalPatientIdentification PatientIdentification
  66. {
  67. get
  68. {
  69. return _PatientInformation;
  70. }
  71. set
  72. {
  73. if (value.ToString().Length != FixedLength_LocalPatientIdentification)
  74. {
  75. throw new FormatException("Patient Information must be " + FixedLength_LocalPatientIdentification + " characters fixed length");
  76. }
  77. _PatientInformation = value;
  78. }
  79. }
  80. public static int FixedLength_LocalRecordingIdentifiaction = 80;
  81. private EDFLocalRecordingIdentification _RecordingInformation;
  82. public EDFLocalRecordingIdentification RecordingIdentification
  83. {
  84. get
  85. {
  86. return _RecordingInformation;
  87. }
  88. set
  89. {
  90. if (value.ToString().Length != EDFHeader.FixedLength_LocalRecordingIdentifiaction)
  91. {
  92. throw new FormatException("Recording Information must be " + EDFHeader.FixedLength_LocalRecordingIdentifiaction + " characters fixed length");
  93. }
  94. _RecordingInformation = value;
  95. }
  96. }
  97. public static int FixedLength_StartDateEDF = 8;
  98. public string StartDateEDF { get; private set; }
  99. public static int FixedLength_StartTimeEDF = 8;
  100. public string StartTimeEDF { get; private set; }
  101. private DateTime _StartDateTime;
  102. public DateTime StartDateTime
  103. {
  104. get { return _StartDateTime; }
  105. set
  106. {
  107. this.StartDateEDF = value.ToString("dd.MM.yy");
  108. this.StartTimeEDF = value.ToString("H.mm.ss");
  109. _StartDateTime = value;
  110. }
  111. }
  112. public static int FixedLength_NumberOfBytes = 8;
  113. private string _NumberOfBytesFixedLengthString = "0";
  114. private int _NumberOfBytes = 0;
  115. public int NumberOfBytes
  116. {
  117. get
  118. {
  119. return _NumberOfBytes;
  120. }
  121. set
  122. {
  123. _NumberOfBytes = value;
  124. _NumberOfBytesFixedLengthString = getFixedLengthString(Convert.ToString(value), FixedLength_NumberOfBytes);
  125. }
  126. }
  127. public static int FixedLength_NumberOfDataRecords = 8;
  128. private string _NumberOfDataRecordsFixedLengthString = "0";
  129. private int _NumberOfDataRecords = 0;
  130. public int NumberOfDataRecords
  131. {
  132. get
  133. {
  134. return _NumberOfDataRecords;
  135. }
  136. set
  137. {
  138. _NumberOfDataRecords = value;
  139. _NumberOfDataRecordsFixedLengthString = getFixedLengthString(Convert.ToString(value), FixedLength_NumberOfDataRecords);
  140. }
  141. }
  142. public static int FixedLength_DuraitonOfDataRecordInSeconds = 8;
  143. private string _DurationOfDataRecordInSecondsFixedLengthString = "0";
  144. private int _DurationOfDataRecordInSeconds = 0;
  145. public int DurationOfDataRecordInSeconds
  146. {
  147. get
  148. {
  149. return _DurationOfDataRecordInSeconds;
  150. }
  151. set
  152. {
  153. _DurationOfDataRecordInSeconds = value;
  154. _DurationOfDataRecordInSecondsFixedLengthString = getFixedLengthString(Convert.ToString(value), FixedLength_DuraitonOfDataRecordInSeconds);
  155. }
  156. }
  157. public static int FixedLength_NumberOfSignalsInDataRecord = 4;
  158. private string _NumberOfSignalsInDataRecordFixedLengthString = "0";
  159. private int _NumberOfSignalsInDataRecord = 0;
  160. public int NumberOfSignalsInDataRecord
  161. {
  162. get
  163. {
  164. return _NumberOfSignalsInDataRecord;
  165. }
  166. set
  167. {
  168. _NumberOfSignalsInDataRecord = value;
  169. _NumberOfSignalsInDataRecordFixedLengthString = getFixedLengthString(Convert.ToString(value), FixedLength_NumberOfSignalsInDataRecord);
  170. }
  171. }
  172. public static int FixedLength_Reserved = 44;
  173. private string _Reserved;
  174. public string Reserved
  175. {
  176. get
  177. {
  178. return _Reserved;
  179. }
  180. set
  181. {
  182. _Reserved = getFixedLengthString(value, FixedLength_Reserved);
  183. }
  184. }
  185. public List<EDFSignal> Signals { get; set; }
  186. private StringBuilder _strHeader = new StringBuilder(string.Empty);
  187. private void parseHeader(char[] header)
  188. {
  189. /**
  190. * replace nulls with space.
  191. */
  192. int i = 0;
  193. foreach (char c in header)
  194. {
  195. if (header[i] == (char)0)
  196. {
  197. header[i] = (char)32;
  198. }
  199. i++;
  200. }
  201. _strHeader.Append(header);
  202. int fileIndex = 0;
  203. char[] version = getFixedLengthCharArrayFromHeader(header, fileIndex, EDFHeader.FixedLength_Version);
  204. this.Version = new string(version);
  205. fileIndex += FixedLength_Version;
  206. char[] localPatientIdentification = getFixedLengthCharArrayFromHeader(header, fileIndex, EDFHeader.FixedLength_LocalPatientIdentification);
  207. fileIndex += EDFHeader.FixedLength_LocalPatientIdentification;
  208. char[] localRecordingIdentification = getFixedLengthCharArrayFromHeader(header, fileIndex, EDFHeader.FixedLength_LocalRecordingIdentifiaction);
  209. fileIndex += EDFHeader.FixedLength_LocalRecordingIdentifiaction;
  210. char[] startDate = getFixedLengthCharArrayFromHeader(header, fileIndex, EDFHeader.FixedLength_StartDateEDF);
  211. this.StartDateEDF = new string(startDate);
  212. fileIndex += EDFHeader.FixedLength_StartDateEDF;
  213. char[] startTime = getFixedLengthCharArrayFromHeader(header, fileIndex, EDFHeader.FixedLength_StartTimeEDF);
  214. this.StartTimeEDF = new string(startTime);
  215. fileIndex += EDFHeader.FixedLength_StartTimeEDF;
  216. char[] numberOfBytesInHeaderRow = getFixedLengthCharArrayFromHeader(header, fileIndex, EDFHeader.FixedLength_NumberOfBytes);
  217. this.NumberOfBytes = int.Parse(new string(numberOfBytesInHeaderRow).Trim());
  218. fileIndex += EDFHeader.FixedLength_NumberOfBytes;
  219. char[] reserved = getFixedLengthCharArrayFromHeader(header, fileIndex, EDFHeader.FixedLength_Reserved);
  220. if (new string(reserved).StartsWith(EDFHeader.EDFContinuous) || new string(reserved).StartsWith(EDFHeader.EDFDiscontinuous))
  221. {
  222. this._isEDFPlus = true;
  223. }
  224. this.Reserved = new string(reserved);
  225. fileIndex += EDFHeader.FixedLength_Reserved;
  226. char[] numberOfDataRecords = getFixedLengthCharArrayFromHeader(header, fileIndex, EDFHeader.FixedLength_NumberOfDataRecords);
  227. this.NumberOfDataRecords = (int.Parse(new string(numberOfDataRecords).Trim()));
  228. fileIndex += EDFHeader.FixedLength_NumberOfDataRecords;
  229. char[] durationOfDataRecord = getFixedLengthCharArrayFromHeader(header, fileIndex, EDFHeader.FixedLength_DuraitonOfDataRecordInSeconds);
  230. this.DurationOfDataRecordInSeconds = int.Parse(new string(durationOfDataRecord).Trim());
  231. fileIndex += EDFHeader.FixedLength_DuraitonOfDataRecordInSeconds;
  232. char[] numberOfSignals = getFixedLengthCharArrayFromHeader(header, fileIndex, EDFHeader.FixedLength_NumberOfSignalsInDataRecord);
  233. this.NumberOfSignalsInDataRecord = int.Parse(new string(numberOfSignals).Trim());
  234. if (this.NumberOfSignalsInDataRecord < 1 || this.NumberOfSignalsInDataRecord > 256)
  235. {
  236. throw new ArgumentException("EDF File has " + this.NumberOfSignalsInDataRecord + " Signals; Number of Signals must be >1 and <=256");
  237. }
  238. fileIndex += EDFHeader.FixedLength_NumberOfSignalsInDataRecord;
  239. this.PatientIdentification = new EDFLocalPatientIdentification(localPatientIdentification);
  240. this.RecordingIdentification = new EDFLocalRecordingIdentification(localRecordingIdentification);
  241. this.StartDateTime = DateTime.ParseExact(this.StartDateEDF + " " + this.StartTimeEDF, "dd.MM.yy HH.mm.ss", System.Globalization.CultureInfo.InvariantCulture);
  242. if (this.IsEDFPlus)
  243. {
  244. if (!this.StartDateTime.Date.Equals(this.RecordingIdentification.RecordingStartDate))
  245. {
  246. throw new ArgumentException("Header StartDateTime does not equal Header.RecordingIdentification StartDate!");
  247. }
  248. else
  249. {
  250. this.RecordingIdentification.RecordingStartDate = this.StartDateTime;
  251. }
  252. }
  253. }
  254. public void parseSignals(char[] signals)
  255. {
  256. this._strHeader.Append(signals);
  257. this.Signals = new List<EDFSignal>();
  258. /**
  259. * replace nulls with space.
  260. */
  261. int h = 0;
  262. foreach (char c in signals)
  263. {
  264. if (signals[h] == (char)0)
  265. {
  266. signals[h] = (char)32;
  267. }
  268. h++;
  269. }
  270. for (int i = 0; i < this.NumberOfSignalsInDataRecord; i++)
  271. {
  272. EDFSignal edf_signal = new EDFSignal();
  273. int charIndex = 0;
  274. char[] label = getFixedLengthCharArrayFromHeader(signals, (i * 16) + (this.NumberOfSignalsInDataRecord * charIndex), 16);
  275. edf_signal.Label = new string(label);
  276. charIndex += 16;
  277. edf_signal.IndexNumber = (i + 1);
  278. char[] transducer_type = getFixedLengthCharArrayFromHeader(signals, (i * 80) + (this.NumberOfSignalsInDataRecord * charIndex), 80);
  279. edf_signal.TransducerType = new string(transducer_type);
  280. charIndex += 80;
  281. char[] physical_dimension = getFixedLengthCharArrayFromHeader(signals, (i * 8) + (this.NumberOfSignalsInDataRecord * charIndex), 8);
  282. edf_signal.PhysicalDimension = new string(physical_dimension);
  283. charIndex += 8;
  284. char[] physical_min = getFixedLengthCharArrayFromHeader(signals, (i * 8) + (this.NumberOfSignalsInDataRecord * charIndex), 8);
  285. edf_signal.PhysicalMinimum = float.Parse(new string(physical_min).Trim());
  286. charIndex += 8;
  287. char[] physical_max = getFixedLengthCharArrayFromHeader(signals, (i * 8) + (this.NumberOfSignalsInDataRecord * charIndex), 8);
  288. edf_signal.PhysicalMaximum = float.Parse(new string(physical_max).Trim());
  289. charIndex += 8;
  290. char[] digital_min = getFixedLengthCharArrayFromHeader(signals, (i * 8) + (this.NumberOfSignalsInDataRecord * charIndex), 8);
  291. edf_signal.DigitalMinimum = float.Parse(new string(digital_min).Trim());
  292. charIndex += 8;
  293. char[] digital_max = getFixedLengthCharArrayFromHeader(signals, (i * 8) + (this.NumberOfSignalsInDataRecord * charIndex), 8);
  294. edf_signal.DigitalMaximum = float.Parse(new string(digital_max).Trim());
  295. charIndex += 8;
  296. char[] prefiltering = getFixedLengthCharArrayFromHeader(signals, (i * 80) + (this.NumberOfSignalsInDataRecord * charIndex), 80);
  297. edf_signal.Prefiltering = new string(prefiltering);
  298. charIndex += 80;
  299. char[] samples_each_datarecord = getFixedLengthCharArrayFromHeader(signals, (i * 8) + (this.NumberOfSignalsInDataRecord * charIndex), 8);
  300. edf_signal.NumberOfSamplesPerDataRecord = int.Parse(new string(samples_each_datarecord).Trim());
  301. charIndex += 8;
  302. this.Signals.Add(edf_signal);
  303. }
  304. }
  305. private string getFixedLengthString(string input, int length)
  306. {
  307. return (input ?? "").Length > length ? (input ?? "").Substring(0, length) : (input ?? "").PadRight(length);
  308. }
  309. private char[] getFixedLengthCharArrayFromHeader(char[] header, int startPoint, int length)
  310. {
  311. char[] ch = new char[length];
  312. Array.Copy(header, startPoint, ch, 0, length);
  313. return ch;
  314. }
  315. public override string ToString()
  316. {
  317. StringBuilder _strHeaderBuilder = new StringBuilder(string.Empty);
  318. _strHeaderBuilder.Append(getFixedLengthString(this.Version, EDFHeader.FixedLength_Version));
  319. _strHeaderBuilder.Append(this.PatientIdentification.ToString());
  320. _strHeaderBuilder.Append(this.RecordingIdentification.ToString());
  321. _strHeaderBuilder.Append(this.StartDateEDF);
  322. _strHeaderBuilder.Append(this.StartTimeEDF);
  323. _strHeaderBuilder.Append(getFixedLengthString(Convert.ToString(this.NumberOfBytes), EDFHeader.FixedLength_NumberOfBytes));
  324. _strHeaderBuilder.Append(this.Reserved);
  325. _strHeaderBuilder.Append(getFixedLengthString(Convert.ToString(this.NumberOfDataRecords), EDFHeader.FixedLength_NumberOfDataRecords));
  326. _strHeaderBuilder.Append(getFixedLengthString(Convert.ToString(this.DurationOfDataRecordInSeconds), EDFHeader.FixedLength_DuraitonOfDataRecordInSeconds));
  327. _strHeaderBuilder.Append(getFixedLengthString(Convert.ToString(this.NumberOfSignalsInDataRecord), EDFHeader.FixedLength_NumberOfSignalsInDataRecord));
  328. foreach (EDFSignal s in this.Signals)
  329. _strHeaderBuilder.Append(getFixedLengthString(s.Label, 16));
  330. foreach (EDFSignal s in this.Signals)
  331. _strHeaderBuilder.Append(getFixedLengthString(s.TransducerType, 80));
  332. foreach (EDFSignal s in this.Signals)
  333. _strHeaderBuilder.Append(getFixedLengthString(s.PhysicalDimension, 8));
  334. foreach (EDFSignal s in this.Signals)
  335. _strHeaderBuilder.Append(getFixedLengthString(Convert.ToString(s.PhysicalMinimum), 8));
  336. foreach (EDFSignal s in this.Signals)
  337. _strHeaderBuilder.Append(getFixedLengthString(Convert.ToString(s.PhysicalMaximum), 8));
  338. foreach (EDFSignal s in this.Signals)
  339. _strHeaderBuilder.Append(getFixedLengthString(Convert.ToString(s.DigitalMinimum), 8));
  340. foreach (EDFSignal s in this.Signals)
  341. _strHeaderBuilder.Append(getFixedLengthString(Convert.ToString(s.DigitalMaximum), 8));
  342. foreach (EDFSignal s in this.Signals)
  343. _strHeaderBuilder.Append(getFixedLengthString(s.Prefiltering, 80));
  344. foreach (EDFSignal s in this.Signals)
  345. _strHeaderBuilder.Append(getFixedLengthString(Convert.ToString(s.NumberOfSamplesPerDataRecord), 8));
  346. foreach (EDFSignal s in this.Signals)
  347. _strHeaderBuilder.Append(getFixedLengthString("", 32));
  348. if (_strHeaderBuilder.ToString().ToCharArray().Length != (256 + (this.Signals.Count * 256)))
  349. {
  350. throw new InvalidOperationException("Header Length must be equal to (256 characters + (number of signals) * 256 ). Header length=" + _strHeaderBuilder.ToString().ToCharArray().Length + " Header=" + _strHeaderBuilder.ToString());
  351. }
  352. _strHeader = _strHeaderBuilder;
  353. return _strHeaderBuilder.ToString();
  354. }
  355. }
  356. }