/// <summary> /// Initializes and returns a blank SigInfoArray object containing numItems SigInfo objects. /// </summary> /// <param name="numItems">Number of SigInfo objects in SigInfoArray</param> /// <param name="errMsg">Storage for verbose error messages, if any.</param> /// <returns>A blank SigInfoArray object of dimension numItems.</returns> public static WFDB_SiginfoArray GetSigInfoArray(int numItems, ref string errMsg) { WFDB_SiginfoArray siArray; errMsg = ""; // First try opening the array: try { siArray = new WFDB_SiginfoArray(numItems); } catch (Exception siarrayException) { while (siarrayException.InnerException != null) { // Drill down: siarrayException = siarrayException.InnerException; } errMsg = siarrayException.ToString() + newLine; MessageBox.Show("Exception occurred executing 'siArray = new WFDB_Siginfo()': \n" + siarrayException.ToString()); return(null); } // No exceptions -- init the array: for (int i = 0; i < numItems; i++) { WFDB_Siginfo newInfo = new WFDB_Siginfo(); // 1234567890 234567890 234567890 234567890 234567890 234567890 234567890 234567890 234567890 234567890 234567890 234567890 // 1 2 3 4 5 6 7 8 9 10 11 12 newInfo.desc = " "; newInfo.fname = " "; newInfo.units = " "; siArray.setitem(i, newInfo); } return(siArray); }
/// <summary> /// Override default behavior to: /// - Save a local copy /// - Get file header info /// - Update iData accordingly /// - Allow using header info to drive the output rates. /// <para>NOTE: This method call GC.Collect() to force garbage collection on the /// managed-code environment. If you are running unmanaged code, before calling /// this method you must ensure that your unmanaged storage allocations are properly /// protected or released.</para> /// </summary> public override void init(ChainInfo iData) { string errMsg = null; // Reset THOROUGHLY: GC.Collect(); GC.WaitForPendingFinalizers(); WfdbAccess.CloseWfdb(); GC.Collect(); GC.WaitForPendingFinalizers(); // Read record header: siArray = WfdbAccess.GetSigInfoArray(numSignals, ref errMsg); bool result = WfdbAccess.GetSignalInfo(recordName, siArray, numSignals, ref errMsg); if (!result) { //System.Windows.Forms.MessageBox("Unable to access header for record '" + recordName + "' in path '" + searchPath + "'!"); Exception ex = new ArgumentException("Unable to access header for record '" + recordName + "' in path '" + searchPath + "'."); throw ex; } // Read useful info from header: WFDB_Siginfo sigInfo = siArray.getitem(0); buffSize = sigInfo.spf; frameBuffer = new int[buffSize]; numSamples = sigInfo.nsamp * sigInfo.spf; sigName = sigInfo.desc; //sampFreq = WfdbAccess.GetSamplingFrequency(recordName); //if (sampFreq < 1) //{ // Problem reading header! // //System.Windows.Forms.MessageBox("Unable to access record '" + recordName + "' in path '" + searchPath + "'!"); // Exception ex = new ArgumentException("Unable to access header for record '" + recordName + "' in path '" + searchPath + "'."); // throw ex; //} adcZeroRef = sigInfo.adczero; adcResBits = sigInfo.adcres; adcMaxValue = (int)Math.Pow(2, adcResBits); baseline = sigInfo.baseline; ampGain = sigInfo.gain; if (ampGain == 0) { // Use default: ampGain = 200; } dataUnits = sigInfo.units; if ((dataUnits == null) || (dataUnits.Length == 0)) { // Assign arbitrarily? dataUnits = "mV"; } // Save a local handle: if (autoSend) { // Point to the input data structure: initValues = iData; } else { // Make our own data structure: initValues = new ChainInfo(); initValues.samplingPeriodSec = iData.samplingPeriodSec; } if (autoSend && doneReading) // We previously terminated the timer - restart it: { // Init the TimerThread: sendTimer = new TimerThread( new System.Threading.ThreadStart(this.next), true); } // Init. what needs it: dispSamples = 0; // just started, nothing retrieved yet doneReading = false; if (initValues.patientInfo == null) { initValues.patientInfo = new PatientInfo("", "", ""); } if (initValues.dataInfo == null) { initValues.dataInfo = new DataInfo(sigInfo.desc, DateTime.Now.ToString()); } // And, apply the REAL values: initValues.dataInfo.BitsPerSample = adcResBits; initValues.dataInfo.ScaleMultiplier = ampGain.ToString(); if (adcResBits == 0) { // Missing some info -- go with a default: initValues.dataInfo.FullScaleReferenceVoltage = "2.0"; initValues.dataInfo.ZeroOffset = "0.0"; initValues.dataInfo.ZeroReferenceVoltage = "-2.0"; } else { initValues.dataInfo.FullScaleReferenceVoltage = ((adcMaxValue - baseline) / ampGain).ToString(); initValues.dataInfo.ZeroOffset = baseline.ToString(); initValues.dataInfo.ZeroReferenceVoltage = (-baseline / ampGain).ToString(); } initValues.dataInfo.ValueUnits = dataUnits; if (initValues.fileInfo == null) { initValues.fileInfo = new FileHandler(); } if (initValues.samplingPeriodSec != stepSize) { // Update the sampling period: initValues.samplingPeriodSec = stepSize; } //// Init. the sampling period: //this.stepSize = initValues.samplingPeriodSec; // Init output buffer: ReadBuffer(); // Apply values and propagate downstream: base.init(iData); // iData may have been changed or not }