/* Disable this constructor -- there is no way right now to set file path & name in * another way! * * /// <summary> * /// Minimal constructor. Note that if you use this constructor, you must * /// set filePath and fileName before calling init(), otherwise an exception * /// will be raised. * /// Also loads header from file. * /// </summary> * /// <param name="secondsPerStep">Interval between samples, in seconds or fraction thereof, * /// e.g. 1 KHz = 1 ms per sample would have secondsPerStep = 0.001. If * /// autoOutput is TRUE and the file header has its own sample period value, * /// then this param is ignored and the value in the file header is used * /// instead.</param> * /// <param name="autoOutput">If TRUE, then we push data out to the Followers AND try to * /// use the sample period value from the file header; if FALSE, we wait * /// for whoever to pull out the data.</param> * public FileReader ( double secondsPerStep, bool autoOutput ) * : base ( secondsPerStep, autoOutput ) * { * } * // */ /// <summary> /// Full constructor: requires file path and file name. /// Also loads header from file. /// </summary> /// <param name="secondsPerStep">Interval between samples, in seconds or fraction thereof, /// e.g. 1 KHz = 1 ms per sample would have secondsPerStep = 0.001. If /// autoOutput is TRUE and the file header has its own sample period value, /// then this param is ignored and the value in the file header is used /// instead.</param> /// <param name="autoOutput">If TRUE, then we push data out to the Followers AND try to /// use the sample period value from the file header; if FALSE, we wait /// for whoever to pull out the data.</param> /// <param name="filePath">Must be an existing file path, with or without trailing slash</param> /// <param name="fileName">Must be an existing file name</param> public FileReader(double secondsPerStep, bool autoOutput, string filePath, string fileName) : base(secondsPerStep, autoOutput) { // Save values: fPath = FileHandler.cleanPath(filePath); fName = FileHandler.cleanFileName(fileName); fPathName = fPath + fName; // Check for existing path: FileHandler.validatePath(fPath); // Make sure file does exist: FileHandler.fileExists(fPathName); // Try opening the new file for reading: FileStream fs = File.OpenRead(fPathName); fs.Close(); // Some inits: // Create the appropriate data structure: initValues = new ChainInfo(); initValues.patientInfo = new PatientInfo("", "", ""); initValues.dataInfo = new DataInfo(); initValues.fileInfo = new FileHandler(); // Read the header from the input file: curReadStartPos = 0; readHeader(); // Update the sampling period: stepSize = initValues.samplingPeriodSec; // Note, we now discard the header data and read it again at Init() time }
/// <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 /// </summary> public override void init(ChainInfo iData) { // Save a local handle: // - If we're AutoSending, we're the authority on the data, so we can override the // contents of iData. That means we point to iData and modify that. // - If we're not AutoSending, we can tell anyone downstream what the actual data // params are, but we shouldn't mess with the original iData to avoid affecting // the source. 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 terminated the timer earlier - restart it: { // Init the TimerThread: sendTimer = new TimerThread( new System.Threading.ThreadStart(this.next), false); } // Init. what needs it: curReadStartPos = 0; doneReading = false; dataFinished = false; // in case it was set to true previously if (initValues.patientInfo == null) { initValues.patientInfo = new PatientInfo("", "", ""); } if (initValues.dataInfo == null) { initValues.dataInfo = new DataInfo( ); } if (initValues.fileInfo == null) { initValues.fileInfo = new FileHandler( ); } // Read the header from the input file: readHeader(); // Init. the sampling period: this.stepSize = initValues.samplingPeriodSec; // Init output buffer: initBuffer(); // Apply values and propagate downstream: base.init(iData); // iData may have been changed or not }
/// <summary> /// Creates a duplicate copy of this object and all its data. /// </summary> /// <returns>A new ChainInfo object identical to this one</returns> public ChainInfo clone() { ChainInfo newData = new ChainInfo(); newData.samplingPeriodSec = this.samplingPeriodSec; newData.patientInfo = this.pInfo.clone(); newData.dataInfo = this.dInfo.clone(); newData.fileInfo = this.fInfo.clone(); return(newData); }
/// <summary> /// Initializes the current object with whatever params it needs, and /// propagates the initialization to all its followers. /// </summary> /// <param name="iData">number of seconds between data samples, e.g. 1 millisec = 0.001</param> public virtual void init(ChainInfo iData) { // Throw exception if null: if (iData == null) { throw new ArgumentNullException("iData", "iData cannot be null!"); } // Throw exception if samplingPeriod is not reasonable: if (iData.samplingPeriodSec <= 0.0) // Must be > 0! { throw new ArgumentOutOfRangeException("iData", iData, "iData.samplingPeriodSec (the number of seconds between data samples) " + "must be greater than zero!"); } // Retrieve what we need: stepPeriod = iData.samplingPeriodSec; // Save (a handle to) the whole thing: initVals = iData; // NOTE: THE TARGET DATA IS SUBJECT TO BEING CHANGED ELSEWHERE! IReceiver follower; for (int i = 0; i < followers.Count; i++) { try { follower = (IReceiver)followers[i]; } catch { // An exception means, followers got changed at just the wrong time // AND it no longer has an i(th) element follower = null; } if (follower != null) { follower.init(iData); } } //lock ( followers ) //{ // foreach ( object cur in followers ) // { // follower = (IReceiver) cur; // follower.init ( iData ); // } //} }
/// <summary> /// Initialize the data run with the appropriate info/parameters. /// Note that a class should tolerate multiple init(...) calls without being destroyed /// then re-instantiated, and there should be nothing carried over from a previous run /// after init(...) has returned. /// </summary> /// <param name="iData">An object containing all necessary/relevant data for this /// data run.</param> public override void init(ChainInfo iData) { base.init(iData); // Re-Init the two progress indicators: lastStep = 0; lastOutput = DateTime.Now; if (autoSend) { // Start the TimerThread now: // - If the step period is less than 0.02 seconds, then only execute // every 0.02 seconds, to avoid overloading the system: if ((stepPeriod * 1000.0) < minTimerIntervalMSec) { sendTimer.Start(minTimerIntervalMSec); // 20 ms. = 0.02 sec. = 50 Hz } else { sendTimer.Start((long)(this.stepPeriod * 1000)); } } }
private void setInitValueByTag(ChainInfo initSet, ChainInfo.tagValuePair tagVal) { // Get the tag: ChainInfo.varTags tag = ChainInfo.getTagFromValue(tagVal.tagName); // Set appropriately -- try ChainInfo first: bool matched = initSet.setByTag(tag, tagVal.tagValue); if (!matched) // It was not an ChainInfo, try DataInfo: { matched = initSet.dataInfo.setByTag(tag, tagVal.tagValue); } if (!matched) // Not a DataInfo, try a PatientInfo { matched = initSet.patientInfo.setByTag(tag, tagVal.tagValue); } if (!matched) { matched = initSet.fileInfo.setByTag(tag, tagVal.tagValue); } if (!matched) { // None of the above -- ???? } }
/// <summary> /// Initialize the object; if this is . /// </summary> /// <param name="iData">Passed up only</param> public override void init(ChainInfo iData) { iData.samplingPeriodSec = stepSize; // Init. the sampling period base.init(iData); }
/// <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 }
/// <summary> /// Returns the tag that the given value corresponds to, or throws an /// exception if there is no match. /// Note that the match must be exact and case-sensitive! /// </summary> /// <param name="tagValue">Tag Value to match to varTags tags</param> /// <returns>The appropriate tag; throws an exception if no match. /// Note that the match must be exact and case-sensitive!</returns> public static ChainInfo.varTags getTagFromLabel(string tagValue) { return(ChainInfo.getTagFromValue(tagValue)); }
/// <summary> /// Initialize myself. /// </summary> /// <param name="iData"></param> public void init(ChainInfo iData) { lastRefresh = DateTime.Now; }