Exemple #1
0
        /// <summary>
        /// Starts sensing and streaming.  Skips starting sensing if Adaptive running.
        /// </summary>
        /// <param name="theSummit">Summit System</param>
        /// <param name="senseConfig">Sense Model</param>
        /// <param name="showErrorMessage">True if you want a popup message on errors or false if show no error popup</param>
        /// <returns>True if success and false if unsuccessful</returns>
        public bool StartSensingAndStreaming(SummitSystem theSummit, SenseModel senseConfig, bool showErrorMessage)
        {
            APIReturnInfo bufferReturnInfo;

            try
            {
                _log.Info("Start Sensing and Streaming");
                //This checks to see if sensing is already enabled.
                //If it is, then skip write sensing state and just start streaming
                SensingState state;
                theSummit.ReadSensingState(out state);
                if (!state.State.ToString().Contains("DetectionLd0") && !state.State.ToString().Contains("DetectionLd1"))
                {
                    _log.Info("Detection is off. Turn sensing on with LD0/LD1 off");
                    // Start sensing
                    //LDO is false because if it is in adaptive then it will bypass this. If not in adaptive, don't need it.
                    bufferReturnInfo = theSummit.WriteSensingState(ConfigConversions.TDSenseStatesConvert(
                                                                       senseConfig.SenseOptions.TimeDomain,
                                                                       senseConfig.SenseOptions.FFT,
                                                                       senseConfig.SenseOptions.Power,
                                                                       false,
                                                                       false,
                                                                       senseConfig.SenseOptions.AdaptiveState,
                                                                       senseConfig.SenseOptions.LoopRecording,
                                                                       senseConfig.SenseOptions.Unused), ConfigConversions.FFTChannelConvert(senseConfig));
                    if (!CheckForReturnError(bufferReturnInfo, "Write Sensing State", showErrorMessage))
                    {
                        return(false);
                    }
                }
                else
                {
                    _log.Warn("Detection is on. SKIP SENSING AND START STREAMING!");
                }
                // Start streaming
                bufferReturnInfo = theSummit.WriteSensingEnableStreams(
                    senseConfig.StreamEnables.TimeDomain,
                    senseConfig.StreamEnables.FFT,
                    senseConfig.StreamEnables.Power,
                    senseConfig.StreamEnables.AdaptiveTherapy,
                    senseConfig.StreamEnables.AdaptiveState,
                    senseConfig.StreamEnables.Accelerometry,
                    senseConfig.StreamEnables.TimeStamp,
                    senseConfig.StreamEnables.EventMarker);
                if (!CheckForReturnError(bufferReturnInfo, "Stream Enables", showErrorMessage))
                {
                    return(false);
                }
            }
            catch (Exception error)
            {
                _log.Error(error);
                return(false);
            }
            return(true);
        }
Exemple #2
0
        /// <summary>
        /// Gets the TDSampleRate for the TimeDomain Channel
        /// Calls TD SampleRateConvert from ConfigConversions class
        /// Checks for disabled time domain channels and returns proper sample rate or disabled for disabled channels
        /// </summary>
        /// <param name="sampleRateIsEnabled">Either true or false depending on value for Time Domain Channel IsEnabled value from config file</param>
        /// <param name="localModel">Sense model</param>
        /// <returns>If the sampleRateIsEnabled variable is set to false, then it returns the TdSampleRates.Disabled. Otherwise it returns the correct TdSampleRates variable for the corresponding TD sample rate from the config file</returns>
        private TdSampleRates GetTDSampleRate(bool sampleRateIsEnabled, SenseModel localModel)
        {
            TdSampleRates the_sample_rate = ConfigConversions.TDSampleRateConvert(localModel.Sense.TDSampleRate);

            if (!sampleRateIsEnabled)
            {
                the_sample_rate = TdSampleRates.Disabled;
            }
            return(the_sample_rate);
        }
Exemple #3
0
        /// <summary>
        /// Calculates the fft bins.
        /// This code is taken from the config ui training code to calculate fft bins
        /// </summary>
        /// <param name="fftSize">Size of the FFT.</param>
        /// <param name="timeRate">The time rate.</param>
        /// <returns>a list of fft bin boundaries</returns>
        public List <double> CalculateFFTBins(FftSizes fftSize, TdSampleRates timeRate)
        {
            int numBins = 0;

            switch (fftSize)
            {
            case FftSizes.Size0064:
                numBins = 64 / 2;
                break;

            case FftSizes.Size0256:
                numBins = 256 / 2;
                break;

            case FftSizes.Size1024:
                numBins = 1024 / 2;
                break;

            default:
                ConfigConversions.DisplayErrorMessageAndClose("Could not convert FFT Size for FFT bins");
                break;
            }
            int rate = 0;

            switch (timeRate)
            {
            case TdSampleRates.Sample0250Hz:
                rate = 250;
                break;

            case TdSampleRates.Sample0500Hz:
                rate = 500;
                break;

            case TdSampleRates.Sample1000Hz:
                rate = 1000;
                break;

            default:
                ConfigConversions.DisplayErrorMessageAndClose("Could not convert TDSampleRate for FFT bins");
                break;
            }

            double binWidth = rate / 2.0 / numBins;

            for (int i = 0; i < numBins; i++)
            {
                bins.Add(i * binWidth);
            }
            return(bins);
        }
Exemple #4
0
        /// <summary>
        /// Gets the power band bins and actual hz values. Program shuts down if can't compute
        /// </summary>
        /// <param name="localModel">SenseModel</param>
        /// <returns>List of PowerBandModel class</returns>
        public List <PowerBandModel> GetPowerBands(SenseModel localModel)
        {
            List <PowerBandModel> powerBandsList = new List <PowerBandModel>();

            try
            {
                CalculateFFTBins(ConfigConversions.FftSizesConvert(localModel.Sense.FFT.FftSize), ConfigConversions.TDSampleRateConvert(localModel.Sense.TDSampleRate));
                binWidth = bins[1] - bins[0];
                CalculateUpperBins();
                CalculateLowerBins();
            }
            catch (Exception e)
            {
                HandleException(e);
            }

            for (int i = 0; i < 8;)
            {
                try
                {
                    PowerBandModel powerBandModel = new PowerBandModel();
                    //Gets the lower index value and upper index value based from the config file value.
                    powerBandModel.lowerIndexBand0 = GetLowerIndex(localModel.Sense.PowerBands[i].ChannelPowerBand[0]);
                    powerBandModel.upperIndexBand0 = GetUpperIndex(localModel.Sense.PowerBands[i].ChannelPowerBand[1]);
                    //This checks to make sure that the upper power bin index is bigger than the lower; cannot have upper index that is less than lower index
                    //if the upper index value is not bigger than the lower, then the upper index is set to lower index for error handling
                    powerBandModel.upperIndexBand0 = CheckThatUpperPowerBandGreaterThanLowerPowerBand(powerBandModel.lowerIndexBand0, powerBandModel.upperIndexBand0);
                    //Actual lower and upper power values are calculated from the users estimated power values from the config file
                    //This is done in the CalculatePowerBins class.  Below saves the actual lower and upper power values in each array to 2 decimal places.
                    //These arrays are instantiated in MainViewModel.cs
                    powerBandModel.lowerActualValueHzBand0 = Math.Round(ActualLowerPowerValue, 2);
                    powerBandModel.UpperActualValueHzBand0 = Math.Round(ActualUpperPowerValue, 2);
                    //increment i so that the next power band can be set. There are 8 (0-7). There are 4 power channels (0-3);
                    i++;
                    //Repeat this step for next power band
                    powerBandModel.lowerIndexBand1         = GetLowerIndex(localModel.Sense.PowerBands[i].ChannelPowerBand[0]);
                    powerBandModel.upperIndexBand1         = GetUpperIndex(localModel.Sense.PowerBands[i].ChannelPowerBand[1]);
                    powerBandModel.upperIndexBand1         = CheckThatUpperPowerBandGreaterThanLowerPowerBand(powerBandModel.lowerIndexBand1, powerBandModel.upperIndexBand1);
                    powerBandModel.lowerActualValueHzBand1 = Math.Round(ActualLowerPowerValue, 2);
                    powerBandModel.upperActualValueHzBand1 = Math.Round(ActualUpperPowerValue, 2);
                    i++;
                    powerBandsList.Add(powerBandModel);
                }
                catch (Exception e)
                {
                    HandleException(e);
                }
            }
            return(powerBandsList);
        }
Exemple #5
0
        /// <summary>
        /// Connects to CTM starting from the 0th value of the list of CTM's and works its way to the Nth.  This considered the right in bilateral
        /// </summary>
        /// <param name="theSummitManager">Summit manager</param>
        /// <param name="theSummit">Summit System</param>
        /// <param name="senseModel">Model for sense from config file</param>
        /// <param name="appModel">Model for application from config file</param>
        /// <param name="_log">Caliburn Micro Logger</param>
        /// <returns>true if connected or false if not connected</returns>
        public override bool ConnectCTM(SummitManager theSummitManager, ref SummitSystem theSummit, SenseModel senseModel, AppModel appModel, ILog _log)
        {
            _log.Info("Checking USB for unbonded CTMs. Please make sure they are powered on.");
            theSummitManager?.GetUsbTelemetry();

            // Retrieve a list of known and bonded telemetry
            List <InstrumentInfo> knownTelemetry = theSummitManager?.GetKnownTelemetry();

            // Check if any CTMs are currently bonded, poll the USB if not so that the user can be prompted to plug in a CTM over USB
            if (knownTelemetry?.Count == 0)
            {
                do
                {
                    // Inform user we will loop until a CTM is found on USBs
                    _log.Warn("No bonded CTMs found, please plug a CTM in via USB...");
                    Thread.Sleep(2000);

                    // Bond with any CTMs plugged in over USB
                    knownTelemetry = theSummitManager?.GetUsbTelemetry();
                } while (knownTelemetry?.Count == 0);
            }

            // Connect to the first CTM available, then try others if it fails
            SummitSystem tempSummit = null;

            try
            {
                for (int i = 0; i < theSummitManager.GetKnownTelemetry().Count; i++)
                {
                    ManagerConnectStatus connectReturn;
                    if (appModel?.CTMBeepEnables == null)
                    {
                        connectReturn = theSummitManager.CreateSummit(out tempSummit, theSummitManager.GetKnownTelemetry()[i], InstrumentPhysicalLayers.Any, senseModel.Mode, senseModel.Ratio, CtmBeepEnables.None);
                    }
                    else if (!appModel.CTMBeepEnables.DeviceDiscovered && !appModel.CTMBeepEnables.GeneralAlert && !appModel.CTMBeepEnables.NoDeviceDiscovered && !appModel.CTMBeepEnables.TelMCompleted && !appModel.CTMBeepEnables.TelMLost)
                    {
                        connectReturn = theSummitManager.CreateSummit(out tempSummit, theSummitManager.GetKnownTelemetry()[i], InstrumentPhysicalLayers.Any, senseModel.Mode, senseModel.Ratio, CtmBeepEnables.None);
                    }
                    else
                    {
                        connectReturn = theSummitManager.CreateSummit(out tempSummit, theSummitManager.GetKnownTelemetry()[i], InstrumentPhysicalLayers.Any, senseModel.Mode, senseModel.Ratio, ConfigConversions.BeepEnablesConvert(appModel));
                    }

                    // Write out the result
                    _log.Info("Create Summit Result: " + connectReturn.ToString());

                    // Break if it failed successful
                    if (tempSummit != null && connectReturn.HasFlag(ManagerConnectStatus.Success))
                    {
                        break;
                    }
                }
            }
            catch (Exception e)
            {
                _log.Error(e);
            }

            // Make sure telemetry was connected to, if not fail
            if (tempSummit == null)
            {
                // inform user that CTM was not successfully connected to
                if (hasShownMessageToUser)
                {
                    MainViewModel.ShowMessageBox("Could not connect to CTM. Check that CTM is placed correctly over INS on chest. If problem persists, please inform researcher of problem.", "Connection to CTM Failed", MessageBoxButton.OK, MessageBoxImage.Error);
                    hasShownMessageToUser = false;
                }
                return(false);
            }
            else
            {
                theSummit = tempSummit;
                return(true);
            }
        }
Exemple #6
0
        /// <summary>
        /// Write Sense Configuration Settings
        /// </summary>
        /// <param name="localModel">The config file to use for sensing parameters</param>
        /// <param name="theSummit">Summit system</param>
        /// <param name="showErrorMessage">True if you want a popup message on errors or false if show no error popup</param>
        /// <returns>true if successfully configuring sensing or false if unsuccessful</returns>
        public bool SummitConfigureSensing(SummitSystem theSummit, SenseModel localModel, bool showErrorMessage)
        {
            APIReturnInfo bufferReturnInfo;

            //This checks to see if sensing is already enabled. This can happen if adaptive is already running and we don't need to configure it.
            //If it is, then skip setting up sensing
            if (CheckIsAdaptiveRunning(theSummit))
            {
                return(true);
            }

            int counter = 5;

            while (counter > 0)
            {
                if (StopSensing(theSummit, showErrorMessage))
                {
                    break;
                }
                else
                {
                    _log.Warn("Could not stop sensing before configure sensing. Trying again...");
                    counter--;
                    Thread.Sleep(500);
                }
            }
            if (counter == 0)
            {
                _log.Warn("Could not stop sensing before configure sensing. Returning false");
                return(false);
            }

            // Create a sensing configuration
            List <TimeDomainChannel> TimeDomainChannels = new List <TimeDomainChannel>(4);

            // Channel Specific configuration - 0
            TimeDomainChannels.Add(new TimeDomainChannel(
                                       GetTDSampleRate(localModel.Sense.TimeDomains[0].IsEnabled, localModel),
                                       ConfigConversions.TdMuxInputsConvert(localModel.Sense.TimeDomains[0].Inputs[0]),
                                       ConfigConversions.TdMuxInputsConvert(localModel.Sense.TimeDomains[0].Inputs[1]),
                                       ConfigConversions.TdEvokedResponseEnableConvert(localModel.Sense.TimeDomains[0].TdEvokedResponseEnable),
                                       ConfigConversions.TdLpfStage1Convert(localModel.Sense.TimeDomains[0].Lpf1),
                                       ConfigConversions.TdLpfStage2Convert(localModel.Sense.TimeDomains[0].Lpf2),
                                       ConfigConversions.TdHpfsConvert(localModel.Sense.TimeDomains[0].Hpf)));

            // Channel Specific configuration - 1
            TimeDomainChannels.Add(new TimeDomainChannel(
                                       GetTDSampleRate(localModel.Sense.TimeDomains[1].IsEnabled, localModel),
                                       ConfigConversions.TdMuxInputsConvert(localModel.Sense.TimeDomains[1].Inputs[0]),
                                       ConfigConversions.TdMuxInputsConvert(localModel.Sense.TimeDomains[1].Inputs[1]),
                                       ConfigConversions.TdEvokedResponseEnableConvert(localModel.Sense.TimeDomains[1].TdEvokedResponseEnable),
                                       ConfigConversions.TdLpfStage1Convert(localModel.Sense.TimeDomains[1].Lpf1),
                                       ConfigConversions.TdLpfStage2Convert(localModel.Sense.TimeDomains[1].Lpf2),
                                       ConfigConversions.TdHpfsConvert(localModel.Sense.TimeDomains[1].Hpf)));

            // Channel Specific configuration - 2
            TimeDomainChannels.Add(new TimeDomainChannel(
                                       GetTDSampleRate(localModel.Sense.TimeDomains[2].IsEnabled, localModel),
                                       ConfigConversions.TdMuxInputsConvert(localModel.Sense.TimeDomains[2].Inputs[0]),
                                       ConfigConversions.TdMuxInputsConvert(localModel.Sense.TimeDomains[2].Inputs[1]),
                                       ConfigConversions.TdEvokedResponseEnableConvert(localModel.Sense.TimeDomains[2].TdEvokedResponseEnable),
                                       ConfigConversions.TdLpfStage1Convert(localModel.Sense.TimeDomains[2].Lpf1),
                                       ConfigConversions.TdLpfStage2Convert(localModel.Sense.TimeDomains[2].Lpf2),
                                       ConfigConversions.TdHpfsConvert(localModel.Sense.TimeDomains[2].Hpf)));

            // Channel Specific configuration - 3
            TimeDomainChannels.Add(new TimeDomainChannel(
                                       GetTDSampleRate(localModel.Sense.TimeDomains[3].IsEnabled, localModel),
                                       ConfigConversions.TdMuxInputsConvert(localModel.Sense.TimeDomains[3].Inputs[0]),
                                       ConfigConversions.TdMuxInputsConvert(localModel.Sense.TimeDomains[3].Inputs[1]),
                                       ConfigConversions.TdEvokedResponseEnableConvert(localModel.Sense.TimeDomains[3].TdEvokedResponseEnable),
                                       ConfigConversions.TdLpfStage1Convert(localModel.Sense.TimeDomains[3].Lpf1),
                                       ConfigConversions.TdLpfStage2Convert(localModel.Sense.TimeDomains[3].Lpf2),
                                       ConfigConversions.TdHpfsConvert(localModel.Sense.TimeDomains[3].Hpf)));

            // Set up the FFT
            FftConfiguration fftChannel = new FftConfiguration(
                ConfigConversions.FftSizesConvert(localModel.Sense.FFT.FftSize),
                localModel.Sense.FFT.FftInterval,
                ConfigConversions.FftWindowAutoLoadsConvert(localModel.Sense.FFT.WindowLoad),
                localModel.Sense.FFT.WindowEnabled,
                ConfigConversions.FftWeightMultipliesConvert(localModel.Sense.FFT.WeightMultiplies),
                localModel.Sense.FFT.StreamSizeBins,
                localModel.Sense.FFT.StreamOffsetBins);

            // Set up the Power channels
            List <PowerChannel> powerChannels = new List <PowerChannel>();
            //This goes through each power channel and gets the lower power band and upper power band.
            //Medtronic api uses bin index values for setting power channels instead of actual values in Hz
            //This calls the CalculatePowerBins class to convert to proper medtronic api values from the user config file
            //User config file has estimated values in Hz for each channel.
            //CalculatePowerBins converts them to actual power values and we are able to get the bin index value from that.
            CalculatePowerBins    calculatePowerBins = new CalculatePowerBins(_log);
            List <PowerBandModel> powerBandsList     = calculatePowerBins.GetPowerBands(localModel);

            if (powerBandsList == null || powerBandsList.Count < 3)
            {
                MessageBox.Show("Error calculating power bins. Please check that power bins are correct in the config file and try again.", "Error", MessageBoxButton.OK, MessageBoxImage.Hand);
                return(false);
            }
            for (int i = 0; i < 4; i++)
            {
                //Add the lower and upper power bands to the power channel
                powerChannels.Add(new PowerChannel(powerBandsList[i].lowerIndexBand0, powerBandsList[i].upperIndexBand0, powerBandsList[i].lowerIndexBand1, powerBandsList[i].upperIndexBand1));
            }
            //Gets the enabled power bands from the sense config file and returns the correct api call for all enabled
            BandEnables theBandEnables = ConfigConversions.PowerBandEnablesConvert(localModel);

            // Set up the miscellaneous settings
            MiscellaneousSensing miscsettings = new MiscellaneousSensing();

            miscsettings.StreamingRate    = ConfigConversions.MiscStreamRateConvert(localModel.Sense.Misc.StreamingRate);
            miscsettings.LrTriggers       = ConfigConversions.MiscloopRecordingTriggersConvert(localModel.Sense.Misc.LoopRecordingTriggersState, localModel.Sense.Misc.LoopRecordingTriggersIsEnabled);
            miscsettings.LrPostBufferTime = localModel.Sense.Misc.LoopRecordingPostBufferTime;
            miscsettings.Bridging         = ConfigConversions.MiscBridgingConfigConvert(localModel.Sense.Misc.Bridging);

            //Writes all sensing information here
            try
            {
                bufferReturnInfo = theSummit.WriteSensingTimeDomainChannels(TimeDomainChannels);
                if (!CheckForReturnError(bufferReturnInfo, "Writing Sensing Time Domain", showErrorMessage))
                {
                    return(false);
                }
                bufferReturnInfo = theSummit.WriteSensingFftSettings(fftChannel);
                if (!CheckForReturnError(bufferReturnInfo, "Writing Sensing FFT", showErrorMessage))
                {
                    return(false);
                }
                bufferReturnInfo = theSummit.WriteSensingPowerChannels(theBandEnables, powerChannels);
                if (!CheckForReturnError(bufferReturnInfo, "Writing Sensing Power", showErrorMessage))
                {
                    return(false);
                }
                bufferReturnInfo = theSummit.WriteSensingMiscSettings(miscsettings);
                if (!CheckForReturnError(bufferReturnInfo, "Writing Sensing Misc", showErrorMessage))
                {
                    return(false);
                }
                bufferReturnInfo = theSummit.WriteSensingAccelSettings(ConfigConversions.AccelSampleRateConvert(localModel.Sense.Accelerometer.SampleRate, localModel.Sense.Accelerometer.SampleRateDisabled));
                if (!CheckForReturnError(bufferReturnInfo, "Writing Sensing Accel", showErrorMessage))
                {
                    return(false);
                }
            }
            catch (Exception error)
            {
                _log.Error(error);
                return(false);
            }
            return(true);
        }