Exemple #1
0
        /// <summary>
        /// Default Constructor for DataSource.
        /// If autoOutput, then this object will output one Sample every secondsPerStep
        /// to its Followers;  if not autoOutput, then it will only generate output when
        /// requested by a call to trigger() or getNextValue() or getNextValues(int).
        /// </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</param>
        /// <param name="autoOutput">If true, then we push data out to the Followers;
        ///					if false, we wait for whoever to pull out the data</param>
        public DataSource(double secondsPerStep, bool autoOutput)
        {
            // Set the interval:
            stepSize = secondsPerStep;

            // Set whether we output on a push or pull scheme:
            autoSend = autoOutput;
            if (autoSend)
            {
                // Init the TimerThread:
                sendTimer = new TimerThread(
                    new System.Threading.ThreadStart(this.next),
                    true);                              // true  -> wait for one call to complete before starting the next one
                //	false );	// false -> do NOT wait for one call to complete before starting the next one
                //			(this can cause overlaps and long queues of waiting threads if the
                //			 code execution should halt for any reason, such as a msg. box or
                //			 a debugger breakpoint).
            }

            // Make sure we init. this, otherwise we risk BIG problems!
            // Note:  each subclass should re-init lastOutput to what makes sense
            // for that class.
            lastOutput      = DateTime.Now;
            this.lastStep   = 0;
            this.lastOutput = DateTime.Now;
        }
Exemple #2
0
        /// <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
        }
Exemple #3
0
        /// <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
        }