/// <summary> /// read block and store them as signal samples for processing /// </summary> /// <param name="seek">seek to block</param> /// <param name="count">blocks to read</param> /// <returns></returns> public static SignalSamples readBlocks(long seek, long count) { SignalSamples samples = new SignalSamples(); if (seek > blocksCount()) { return(samples); } long cnt = 0; if (seek < 0) { setPosition(0); cnt = count + seek; } else { setPosition(seek); cnt = count; } for (int i = 0; i < cnt; i++) { if (remainingBlocks() < 2) { return(samples); } readBlock(ref samples); } return(samples); }
/// <summary> /// load and filter signal /// </summary> /// <param name="slider">slider</param> /// <returns></returns> public static SignalSamples load(Slider slider) { // skip if file not exist if (!FileHandler.available()) { return(null); } // load samples Settings set = Settings.instance(); int sampleRate = FileHandler.readSampleRate(); SignalSamples samples = FileHandler.readBlocks(slider.seek, slider.blocks); samples = samples.Normalize(); samples.sampleRate = sampleRate; // find signal amplitude Signal deltaGreat = samples.FindMax() - samples.FindMin(); // 2x 12 hz filter if (set.noise12Hz) { samples.Filter(12, sampleRate / 2, 1.3f); samples.Filter(12, sampleRate / 2, 1.3f); } // 20 hz filter if (set.noise20Hz) { samples.Filter(20, sampleRate / 2, 1.3f); samples.Filter(20, sampleRate / 2, 1.3f); } // 45 hz filter if (set.noise45Hz) { samples.Filter(45, sampleRate / 2, 1.3f); } // 50hz or 60hz noise if (set.noiseCustom > 0) { samples.Filter(set.noiseCustom, sampleRate / 2, 1); } // notch filter if (set.noiseNotch) { samples = FilterNotch.Process(samples, 400, 0.1f); } // find signal loss enerrgy amplitude Signal deltaLess = samples.FindMax() - samples.FindMin(); // amplify loosed amplitude samples.Amplify(deltaGreat, deltaLess); // load file description FileHandler.id = XmlClass <EcgStatistic> .Load(FileHandler.p + ".xml", SerializedFormat.Document); return(samples); }
/// <summary> /// read single block as signal /// </summary> /// <param name="samples"></param> private static void readBlock(ref SignalSamples samples) { byte[] header = io.ReadBytes(8); double adcmax = 0x800000; byte SDM = header[0]; byte R1 = header[1]; byte R2 = header[2]; byte R3 = header[3]; int odr = 102400 * SDM / R1 / R2 / R3; if (R2 == 4 || R2 == 8) { if (R3 == 6 || R3 == 12) { adcmax = 0xF30000; } else { adcmax = 0x800000; } } else if (R2 == 5) { if (R3 == 6 || R3 == 12) { adcmax = 0xB964F0; } else { adcmax = 0xC35000; } } else if (R2 == 6) { if (R3 == 6 || R3 == 12) { adcmax = 0xE6A900; } else { adcmax = 0xF30000; } } for (int i = 0; i < 56; i++) { double sample1 = ((Math.Pow(2, 16) * io.ReadByte() + Math.Pow(2, 8) * io.ReadByte() + io.ReadByte()) / adcmax - 0.5) * 4.8 / 3.5 * 1000; double sample2 = ((Math.Pow(2, 16) * io.ReadByte() + Math.Pow(2, 8) * io.ReadByte() + io.ReadByte()) / adcmax - 0.5) * 4.8 / 3.5 * 1000; double sample3 = ((Math.Pow(2, 16) * io.ReadByte() + Math.Pow(2, 8) * io.ReadByte() + io.ReadByte()) / adcmax - 0.5) * 4.8 / 3.5 * 1000; Signal ss = new Signal() { lead1 = (float)sample1, lead2 = (float)sample2, lead3 = (float)sample3 }; samples.Add(ss); } }
/// <summary> /// thread for faster analysing /// </summary> void run() { // skip if file not available if (!FileHandler.available()) { return; } progressBar1.Value = 0; // load sample rate sampleRate = FileHandler.readSampleRate(); // load samples samples = FileHandler.load(slider1); progressBar1.Value = 20; Application.DoEvents(); bool fst = false; // if signal was ecg if (decg.Checked) { // set samples graph1.samples = samples; graph1.sampleRate = sampleRate; graph1.ylabel = "mv"; } else { graph1.samples = new SignalSamples(); graph1.samples.sampleRate = 0; graph1.sampleRate = 0; bool stop = false; // initialize ecg arrays int[] tr = new int[3]; int[] offset = new int[3]; List <float>[] sigz = new List <float> [3]; EcgCharacteristics[] last = new EcgCharacteristics[3]; EcgCharacteristics[] now = new EcgCharacteristics[3]; // define ecg arrays for (int i = 0; i < 3; i++) { sigz[i] = new List <float>(); offset[i] = sampleRate; // detect first ecg signal last[i] = samples.FindDelta(i + 1, 0, offset[i]); tr[i] = 0; } // loop until signal is end do { for (int i = 0; i < 3; i++) { // detect second ecg signal now[i] = samples.FindDelta(i + 1, last[i].lastCharacteristic(), offset[i]); // find distrance between two pulses offset[i] = Math.Abs(now[i]["R"].idx - last[i]["R"].idx); // if the heart beat(pulse rate) between exact range if (offset[i] > 0 && offset[i] < sampleRate) { // find heart beat sample rate if (!fst) { graph1.samples.sampleRate += offset[i]; if (i == 2) { fst = true; } } float hpr = 0; // calculate ST line if (dst.Checked) { hpr = (now[i]["ST"].value - now[i]["Q"].value); } else if (dpr.Checked) // calculate heart beat { hpr = 60.0f / (float)(offset[i] / (float)sampleRate); } sigz[i].Add(hpr); } else { // if pulse rate was not reliable set offset as default sample rate offset[i] = sampleRate; } // if ecg data was not reliable try again if (now[i]["c"].idx <= 0 || now[i]["T"].idx <= 0) { tr[i]++; } // set last ecg signal if signal was out of range if (now[i].lastCharacteristic() <= last[i].lastCharacteristic()) { now[i]["c"].idx = last[i].lastCharacteristic() + offset[i]; } // skip if signal was out of range if (now[i].lastCharacteristic() + offset[i] > samples.Count) { tr[i] = 40; } // set last[i] = now[i]; } // return when data was end if (tr[0] > 30 && tr[1] > 30 && tr[2] > 30) { stop = true; } } while (!stop); // find maximum signal range int max = sigz[0].Count; for (int i = 0; i < 3; i++) { if (sigz[i].Count > max) { max = sigz[i].Count; } } // insert collected data as samples for (int i = 0; i < max; i++) { Signal sig = new Signal(); for (int j = 0; j < 3; j++) { if (i < sigz[j].Count) { sig[j + 1] = sigz[j][i]; } } graph1.samples.Add(sig); } // show results if (dpr.Checked) { graph1.ylabel = ""; } else if (dst.Checked) { graph1.ylabel = "mv"; } progressBar1.Value = 100; graph1.samples.sampleRate = (int)((float)sampleRate / (float)graph1.samples.sampleRate / 3.0f + 1); graph1.sampleRate = graph1.samples.sampleRate; graph1.samples.NoiseReduction(3); } graph1.zoom = (float)graph1.samples.Count / (float)graph1.sampleRate; graph1.Refresh(); working = false; }