示例#1
0
        private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            Spectrometer spectrometer = e.Result as Spectrometer;

            if (spectrometer == currentSpectrometer)
            {
                updateStartButton(false);
            }

            // should we auto-exit?
            if (opts.autoStart && opts.scanCount > 0)
            {
                bool shutdown = true;
                lock (spectrometers)
                {
                    foreach (Spectrometer s in spectrometers)
                    {
                        SpectrometerState ss = spectrometerStates[s];
                        if (ss.scanCount < opts.scanCount)
                        {
                            shutdown = false;
                        }
                    }
                }
                if (shutdown)
                {
                    Close();
                }
            }
        }
示例#2
0
        ////////////////////////////////////////////////////////////////////////
        // Business Logic
        ////////////////////////////////////////////////////////////////////////

        void initializeSpectrometer(Spectrometer s)
        {
            SpectrometerState state = new SpectrometerState(s, opts);

            // TODO: move into SpectrometerState ctor
            state.worker.DoWork             += backgroundWorker_DoWork;
            state.worker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;

            spectrometerStates.Add(s, state);

            chart1.Series.Add(state.series);

            if (!s.isARM)
            {
                s.triggerSource = TRIGGER_SOURCE.INTERNAL;
            }

            s.integrationTimeMS              = s.eeprom.minIntegrationTimeMS;
            numericUpDownIntegTimeMS.Value   = s.eeprom.minIntegrationTimeMS;
            numericUpDownIntegTimeMS.Minimum = s.eeprom.minIntegrationTimeMS;
            // numericUpDownIntegTimeMS.Maximum = s.eeprom.maxIntegrationTimeMS; // disabled to allow long integration times

            if (s.pixels > 0)
            {
                logger.info("Found {0} {1} with {2} pixels from {3:f2} to {4:f2}nm",
                            s.model, s.serialNumber, s.pixels, s.wavelengths[0], s.wavelengths[s.wavelengths.Length - 1]);
            }
            else
            {
                logger.error("Found [model: {0}] [serial: {1}] with {2} pixels", s.model, s.serialNumber, s.pixels);
            }

            // default to high-resolution laser power
            s.laserPowerResolution = Spectrometer.LaserPowerResolution.LASER_POWER_RESOLUTION_1000;
        }
示例#3
0
        ////////////////////////////////////////////////////////////////////////
        // BackgroundWorker: GUI Updates
        ////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Update the graph at 10Hz regardless of integration time(s)
        /// (prevents CPU overruns).
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void backgroundWorkerGUIUpdate_DoWork(object sender, DoWorkEventArgs e)
        {
            logger.debug("GUIUpdate thread starting");
            BackgroundWorker worker            = sender as BackgroundWorker;
            ushort           lowFreqOperations = 0;

            while (true)
            {
                Thread.Sleep(100);
                if (worker.CancellationPending || shutdownPending)
                {
                    break;
                }

                chart1.BeginInvoke(new MethodInvoker(delegate { updateGraph(); }));

                // once a second, update temperatures
                if (lowFreqOperations++ > 10)
                {
                    foreach (Spectrometer s in spectrometers)
                    {
                        if (!s.isARM)
                        {
                            SpectrometerState state = spectrometerStates[s];
                            state.detTempDegC = s.detectorTemperatureDegC;
                        }
                    }
                    lowFreqOperations = 0;
                }
            }
            logger.debug("GUIUpdate thread exiting");
        }
示例#4
0
        private void checkBoxTakeDark_CheckedChanged(object sender, EventArgs e)
        {
            SpectrometerState state = spectrometerStates[currentSpectrometer];

            lock (spectrometers)
            {
                if (checkBoxTakeDark.Checked)
                {
                    if (state.spectrum != null)
                    {
                        currentSpectrometer.dark = state.spectrum;
                        state.spectrum           = new double[currentSpectrometer.pixels];

                        checkBoxTakeReference.Enabled = true;
                    }
                }
                else
                {
                    currentSpectrometer.dark = null;

                    // if we have no dark, then we can have no reference
                    state.reference = null;
                    checkBoxTakeReference.Checked     =
                        checkBoxTakeReference.Enabled = false;

                    // if we have no dark, we can do no processing
                    radioButtonModeScope.Checked = true;
                }
            }
        }
示例#5
0
        void updateGraph()
        {
            lock (spectrometers)
            {
                foreach (Spectrometer spectrometer in spectrometers)
                {
                    SpectrometerState state = spectrometerStates[spectrometer];

                    if (state.spectrum == null)
                    {
                        // logger.debug("not graphing because spectrum null");
                        continue;
                    }

                    Series series = state.series;
                    series.Points.Clear();

                    if (graphWavenumbers && spectrometer.wavenumbers != null)
                    {
                        for (uint i = 0; i < spectrometer.pixels; i++)
                        {
                            series.Points.AddXY(spectrometer.wavenumbers[i], state.spectrum[i]);
                        }
                    }
                    else
                    {
                        for (uint i = 0; i < spectrometer.pixels; i++)
                        {
                            series.Points.AddXY(spectrometer.wavelengths[i], state.spectrum[i]);
                        }
                    }

                    // extra handling for current spectrometer
                    if (spectrometer == currentSpectrometer)
                    {
                        /// has spectra, so allow darks and traces
                        checkBoxTakeDark.Enabled   =
                            buttonAddTrace.Enabled =
                                buttonSave.Enabled = true;

                        labelDetTempDegC.Text = String.Format("{0:f1}°C", state.detTempDegC);
                    }
                }

                chart1.ChartAreas[0].AxisY.IsStartedFromZero = false;
                chart1.ChartAreas[0].RecalculateAxesScale();
            }
        }
示例#6
0
        private void buttonStart_Click(object sender, EventArgs e)
        {
            SpectrometerState state = spectrometerStates[currentSpectrometer];

            if (!state.running)
            {
                logger.info("Starting acquisition");
                updateStartButton(true);
                state.worker.RunWorkerAsync(currentSpectrometer);
            }
            else
            {
                logger.info("Stopping acquisition");
                state.worker.CancelAsync();
            }
        }
示例#7
0
        ////////////////////////////////////////////////////////////////////////
        // Background Worker: Acquisition Threads
        ////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Perform all acquisitions in background threads so the GUI stays responsive.
        /// </summary>
        /// <remarks>
        /// Note that this method is used by potentially several different
        /// BackgroundWorkers in parallel (one per attached spectrometer).
        ///
        /// TODO: rename backgroundWorkerAcquisition
        /// </remarks>
        private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            Spectrometer      spectrometer = (Spectrometer)e.Argument;
            SpectrometerState state        = spectrometerStates[spectrometer];

            string prefix = String.Format("Worker.{0}.{1}", spectrometer.model, spectrometer.serialNumber);

            state.running = true;

            BackgroundWorker worker = sender as BackgroundWorker;

            while (true)
            {
                // end thread if we've been asked to cancel
                if (worker.CancellationPending)
                {
                    break;
                }

                // logger.debug("workerAcquisition: getting spectrum");
                double[] raw = spectrometer.getSpectrum();
                if (raw == null)
                {
                    Thread.Sleep(100);
                    continue;
                }

                // process for graphing
                lock (spectrometers)
                    state.processSpectrum(raw);

                // end thread if we've completed our allocated acquisitions
                if (opts.scanCount > 0 && state.scanCount >= opts.scanCount)
                {
                    break;
                }

                int delayMS = (int)Math.Max(100, opts.scanIntervalSec * 1000);
                if (delayMS > 0)
                {
                    Thread.Sleep(delayMS);
                }
            }

            state.running = false;
            e.Result      = spectrometer; // pass spectrometer handle to _Completed callback
        }
示例#8
0
        private void buttonAddTrace_Click(object sender, EventArgs e)
        {
            SpectrometerState state = spectrometerStates[currentSpectrometer];

            Series trace = new Series();

            trace.IsVisibleInLegend = false;
            trace.ChartType         = SeriesChartType.Line;

            foreach (DataPoint p in state.series.Points)
            {
                trace.Points.Add(p);
            }

            traces.Add(trace);
            chart1.Series.Add(trace);

            buttonClearTraces.Enabled = true;
        }
示例#9
0
        private void buttonSave_Click(object sender, EventArgs e)
        {
            if (opts.saveDir.Length == 0)
            {
                if (!initSaveDir())
                {
                    return;
                }
            }

            // More complex implementations could save all spectra from all spectrometers;
            // or include snapped traces; or export directly to multi-tab Excel spreadsheets.

            lock (spectrometers)
            {
                SpectrometerState state = spectrometerStates[currentSpectrometer];
                if (state.spectrum == null)
                {
                    return;
                }

                state.save();
            }
        }
示例#10
0
        private void checkBoxTakeReference_CheckedChanged(object sender, EventArgs e)
        {
            SpectrometerState state = spectrometerStates[currentSpectrometer];

            lock (spectrometers)
            {
                bool success = false;
                if (checkBoxTakeReference.Checked)
                {
                    if (state.spectrum != null)
                    {
                        // business logic should ensure this, but just in case
                        if (currentSpectrometer.dark != null)
                        {
                            state.reference = new double[state.spectrum.Length];
                            Array.Copy(state.spectrum, state.reference, state.spectrum.Length);
                            success = true;

                            radioButtonModeTransmission.Enabled = true;
                            radioButtonModeAbsorbance.Enabled   = true;
                        }
                        else
                        {
                            logger.error("Can't take reference without dark");
                        }
                    }
                }

                if (!success)
                {
                    state.reference = null;
                    radioButtonModeTransmission.Enabled = false;
                    radioButtonModeAbsorbance.Enabled   = false;
                }
            }
        }
示例#11
0
        void updateCurrentSpectrometer()
        {
            if (currentSpectrometer == null)
            {
                groupBoxSettings.Enabled              =
                    groupBoxControl.Enabled           =
                        toolStripMenuItemTest.Enabled = false;
                return;
            }

            SpectrometerState state = spectrometerStates[currentSpectrometer];

            // update tree view
            // if (!state.spectrometer.isARM())
            treeViewSettings_DoubleClick(null, null);

            // update start button
            updateStartButton(spectrometerStates[currentSpectrometer].running);

            // update basic controls
            numericUpDownIntegTimeMS.Value     = currentSpectrometer.integrationTimeMS;
            numericUpDownBoxcarHalfWidth.Value = currentSpectrometer.boxcarHalfWidth;
            numericUpDownScanAveraging.Value   = currentSpectrometer.scanAveraging;

            // update TEC controls
            numericUpDownDetectorSetpointDegC.Minimum = (int)currentSpectrometer.eeprom.detectorTempMin;
            numericUpDownDetectorSetpointDegC.Maximum = (int)currentSpectrometer.eeprom.detectorTempMax;
            numericUpDownDetectorSetpointDegC.Enabled = currentSpectrometer.eeprom.hasCooling;

            // update laser controls
            if (currentSpectrometer.hasLaser)
            {
                numericUpDownLaserPowerPerc.Enabled =
                    checkBoxLaserEnable.Enabled     = true;
                checkBoxLaserEnable.Checked         = currentSpectrometer.laserEnabled;
            }
            else
            {
                numericUpDownLaserPowerPerc.Enabled =
                    checkBoxLaserEnable.Enabled     =
                        checkBoxLaserEnable.Checked = false;
            }

            checkBoxTakeDark.Enabled      = buttonSave.Enabled = state.spectrum != null;
            checkBoxTakeReference.Enabled = state.spectrum != null && currentSpectrometer.dark != null;

            if (state.processingMode == SpectrometerState.ProcessingModes.SCOPE)
            {
                radioButtonModeScope.Checked = true;
            }
            else if (state.processingMode == SpectrometerState.ProcessingModes.TRANSMISSION)
            {
                radioButtonModeTransmission.Checked = true;
            }
            else
            {
                radioButtonModeAbsorbance.Checked = true;
            }

            groupBoxSettings.Enabled              =
                groupBoxControl.Enabled           =
                    toolStripMenuItemTest.Enabled =
                        labelDetTempDegC.Visible  = true;
        }