private void BwAnalyze(object sender, DoWorkEventArgs e)
        {
            Tuple <List <double>, List <double> > data = (Tuple <List <double>, List <double> >)e.Argument;
            string res = ResultString((int)RamanAnalyzer.Analysis(data.Item1, data.Item2));

            e.Result = new Result(ResultStatus.SUCCESS, null, res);
        }
        void Calibrate()
        {
            List <double> wl     = _phosSpectra[(int)(CurrentSpectraItem - 1)].Spectrum.Select(p => p.X).ToList();
            List <double> counts = _phosSpectra[(int)(CurrentSpectraItem - 1)].Spectrum.Select(p => p.Y).ToList();

            SpectrumAnalyzer analyzer = new SpectrumAnalyzer(wl, counts);
            string           error;

            if (!analyzer.AutoCalibrate(out error))
            {
                MessageBox.Show(error, "Calibration failed, try another spectrum");
                return;
            }

            RamanAnalyzer.Analysis(wl, counts);
        }
        void BwBatchMeasure(object sender, DoWorkEventArgs e)
        {
            List <Point> posiList = (List <Point>)e.Argument;

            if (posiList.Count <= 1)
            {
                e.Result = new Result(ResultStatus.ERROR, "No stones selected for measurement");
                Debug.WriteLine("no selected positions");
            }
            else
            {
                try
                {
                    BackgroundWorker bw = sender as BackgroundWorker;
                    int progress        = 0;
                    int step            = (int)(100.0 / (posiList.Count - 1) + 0.99);
                    bw.ReportProgress(step / 2);
                    _statusVM.IsBusy = true;

                    _measurementType = MeasurementType.MEASURE;
                    // 0. capture image before measurement
                    _cameraVM.StartEnqueue();
                    if (!_whMeasureControl.WaitOne(2000))
                    {
                        // todo: error in capture image
                        e.Result = new Result(ResultStatus.ERROR, "Failed to enqueue image");
                        return;
                    }
                    // camera reset to continue mode for display
                    _cameraVM.StopEnqueue();
                    ulong timeStamp = (ulong)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds;
                    _camResultsPre = new CamPhosResults(timeStamp, _cameraVM.GetImageQueue().ToList());
                    Thread.Sleep(200);

                    // loop through the positionlist to do each measurement
                    for (int i = 1; i < posiList.Count; i++)
                    {
                        // 1. move to ref position (EndPoint)
                        double deltaX = -(posiList[i].X - posiList[i - 1].X);
                        double deltaY = posiList[i].Y - posiList[i - 1].Y;

                        if (!_xyzAxesVM.MoveTo(deltaX, deltaY, false))
                        {
                            e.Result = new Result(ResultStatus.ERROR, "Failed to move stone to the reference position");
                            Debug.WriteLine("batchmeasure: MoveTo({0}, {1}) failed", deltaX, deltaY);
                            return;
                        }
                        Thread.Sleep(300);

                        // 2. turn on laser
                        if (!_xyzAxesVM.SetLaserOnOff(true))
                        {
                            e.Result = new Result(ResultStatus.ERROR, "Failed to turn on laser");
                            Debug.WriteLine("batchmeasure: SetLaserOnOff(true) failed");
                            return;
                        }
                        Thread.Sleep(1000);

                        // 3. capture image
                        _cameraVM.StartEnqueue();
                        if (!_whMeasureControl.WaitOne(2000))
                        {
                            // todo: error in capture image
                            e.Result = new Result(ResultStatus.ERROR, "Failed to enqueue image");
                            Debug.WriteLine("batchmeasure: StartEnqueue failed");
                            return;
                        }
                        // camera reset to continue mode for display
                        _cameraVM.StopEnqueue();
                        timeStamp       = (ulong)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds;
                        _camPhosResults = new CamPhosResults(timeStamp, _cameraVM.GetImageQueue().ToList());
                        Thread.Sleep(300);

                        // 4. spectrometer measure
                        if (mappingMeasure)
                        {
                            ResetSpectroResults();

                            double integrationTime = GlobalVariables.spectrometerSettings.IntegrationTime;
                            uint   numAverages     = GlobalVariables.spectrometerSettings.NumAverages;

                            Callback MeasurementEnd = MeasurementCompleteCallback;
                            if (!_spectrometerVM.StartPhosphorescenceMeasurement(GlobalVariables.spectrometerSettings.Delay, GlobalVariables.spectrometerSettings.Counts, integrationTime, numAverages, MeasurementEnd, out string error))
                            {
                                e.Result = new Result(ResultStatus.ERROR, "Failed in start phosphorescence measurement");
                                return;
                            }
                            if (!_whMeasureControl.WaitOne(15000))
                            {
                                // todo: error in getting spectrometer data
                                e.Result = new Result(ResultStatus.ERROR, "Failed in phosphorescence measurement");
                                return;
                            }

                            // save spectrum data to _spectroResults
                            for (int m = 0; m < _spectrometerPhosResults.Spectra.Count; m++)
                            {
                                _spectroResults.Spectra.Add(_spectrometerPhosResults.Spectra[m]);
                            }
                        }
                        else
                        {
                            Stopwatch watch  = Stopwatch.StartNew();
                            int       factor = 0;
                            int       index  = 2;
                            _peakInfoList.Clear();
                            ResetSpectroResults();
                            while (index >= 0 && index <= 4)
                            {
                                Console.WriteLine("spectrum parameter index: {0}", index);
                                double integrationTime = SpectrumParameters[index].Item1;
                                uint   numAverages     = SpectrumParameters[index].Item2;

                                Callback MeasurementEnd = MeasurementCompleteCallback;
                                if (!_spectrometerVM.StartPhosphorescenceMeasurement(GlobalVariables.spectrometerSettings.Delay, GlobalVariables.spectrometerSettings.Counts, integrationTime, numAverages, MeasurementEnd, out string error))
                                {
                                    e.Result = new Result(ResultStatus.ERROR, "Failed in start phosphorescence measurement");
                                    return;
                                }
                                if (!_whMeasureControl.WaitOne(15000))
                                {
                                    // todo: error in getting spectrometer data
                                    e.Result = new Result(ResultStatus.ERROR, "Failed in phosphorescence measurement");
                                    return;
                                }

                                // save spectrum data to _spectroResults
                                for (int m = 0; m < _spectrometerPhosResults.Spectra.Count; m++)
                                {
                                    _spectroResults.Spectra.Add(_spectrometerPhosResults.Spectra[m]);
                                }

                                // analyze spectrum data
                                List <double>         wl       = _spectrometerPhosResults.Spectra[0].Spectrum.Select(p => p.X).ToList();
                                List <double>         counts   = _spectrometerPhosResults.Spectra[0].Spectrum.Select(p => p.Y).ToList();
                                List <PeakDetectInfo> peakInfo = new List <PeakDetectInfo>();
                                _diamondResult = RamanAnalyzer.Analysis(wl, counts, out peakInfo);

                                if (_diamondResult == ANALYZER_RESULT.ERROR || _diamondResult == ANALYZER_RESULT.ERROR_SPIKE)
                                {
                                    break;
                                }

                                if (_diamondResult == ANALYZER_RESULT.NONE)
                                {
                                    _peakInfoList.Add(peakInfo);
                                    if (factor == 0 || factor == 1)
                                    {
                                        index++;
                                        factor = 1;
                                        continue;
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                                else if (_diamondResult == ANALYZER_RESULT.SATURATED)
                                {
                                    _peakInfoList.Add(peakInfo);
                                    if (factor == 0 || factor == -1)
                                    {
                                        index--;
                                        factor = -1;
                                        continue;
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                                else if (_diamondResult == ANALYZER_RESULT.NON_DIAMOND)
                                {
                                    if (index >= 2)
                                    {
                                        _peakInfoList.Clear();
                                    }
                                    _peakInfoList.Add(peakInfo);
                                    break;
                                }
                                else
                                {
                                    _peakInfoList.Clear();
                                    break;
                                }
                            }

                            watch.Stop();
                            long ms = watch.ElapsedMilliseconds;
                            Console.WriteLine("spectrum measurement spend: {0}", ms);

                            if (_peakInfoList.Count >= 2)
                            {
                                _diamondResult = SpectrumAnalyzer.TestAggregate(_peakInfoList);
                            }
                        }
                        Thread.Sleep(300);

                        // 5. turn off laser
                        if (!_xyzAxesVM.SetLaserOnOff(false))
                        {
                            e.Result = new Result(ResultStatus.ERROR, "Failed to turn off laser");
                            Debug.WriteLine("batchmeasure: SetLaserOnOff(false) failed");
                            return;
                        }
                        Thread.Sleep(300);

                        CamResList.Add(_camPhosResults);
                        SpeResList.Add(_spectroResults);
                        DiamondResList.Add(_diamondResult);
                        PeakInfoListList.Add(_peakInfoList);

                        bw.ReportProgress(progress += step);
                    }
                    e.Result = new Result(ResultStatus.SUCCESS, null);
                } catch (Exception ex)
                {
                    e.Result = new Result(ResultStatus.ERROR, ex.Message);
                    Debug.WriteLine(ex.Message);
                }
            }
        }
        void BwMeasure(object sender, DoWorkEventArgs e)
        {
            try
            {
                BackgroundWorker bw = sender as BackgroundWorker;
                int progress        = 0;
                int step            = 25;
                bw.ReportProgress(step / 2);
                _statusVM.IsBusy = true;

                _measurementType = MeasurementType.MEASURE;
                // 0. capture image before measurement
                _cameraVM.StartEnqueue();
                if (!_whMeasureControl.WaitOne(2000))
                {
                    // todo: error in capture image
                    e.Result = new Result(ResultStatus.ERROR, "Failed to enqueue image");
                    return;
                }
                // camera reset to continue mode for display
                _cameraVM.StopEnqueue();
                ulong timeStamp = (ulong)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds;
                _camResultsPre = new CamPhosResults(timeStamp, _cameraVM.GetImageQueue().ToList());
                Thread.Sleep(200);

                // 1. turn on laser
                if (!_xyzAxesVM.SetLaserOnOff(true))
                {
                    e.Result = new Result(ResultStatus.ERROR, "Failed to turn on the laser");
                    return;
                }
                bw.ReportProgress(progress += step);
                Thread.Sleep(1000);

                // 1.5 capture image
                _cameraVM.StartEnqueue();
                if (!_whMeasureControl.WaitOne(2000))
                {
                    // todo: error in capture image
                    e.Result = new Result(ResultStatus.ERROR, "Failed to enqueue image");
                    return;
                }
                // camera reset to continue mode for display
                _cameraVM.StopEnqueue();
                timeStamp       = (ulong)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds;
                _camPhosResults = new CamPhosResults(timeStamp, _cameraVM.GetImageQueue().ToList());
                Thread.Sleep(200);

                bw.ReportProgress(progress += step);
                // 2. spectrometer measure
                Stopwatch watch  = Stopwatch.StartNew();
                int       factor = 0;
                int       index  = 2;
                _peakInfoList.Clear();
                ResetSpectroResults();
                while (index >= 0 && index <= 4)
                {
                    Console.WriteLine("spectrum parameter index: {0}", index);
                    double integrationTime = SpectrumParameters[index].Item1;
                    uint   numAverages     = SpectrumParameters[index].Item2;

                    Callback MeasurementEnd = MeasurementCompleteCallback;
                    if (!_spectrometerVM.StartPhosphorescenceMeasurement(GlobalVariables.spectrometerSettings.Delay, GlobalVariables.spectrometerSettings.Counts, integrationTime, numAverages, MeasurementEnd, out string error))
                    {
                        e.Result = new Result(ResultStatus.ERROR, "Failed in start phosphorescence measurement");
                        return;
                    }
                    if (!_whMeasureControl.WaitOne(15000))
                    {
                        // todo: error in getting spectrometer data
                        e.Result = new Result(ResultStatus.ERROR, "Failed in phosphorescence measurement");
                        return;
                    }

                    // save spectrum data to _spectroResults
                    for (int i = 0; i < _spectrometerPhosResults.Spectra.Count; i++)
                    {
                        _spectroResults.Spectra.Add(_spectrometerPhosResults.Spectra[i]);
                    }

                    // analyze spectrum data
                    List <double>         wl       = _spectrometerPhosResults.Spectra[0].Spectrum.Select(p => p.X).ToList();
                    List <double>         counts   = _spectrometerPhosResults.Spectra[0].Spectrum.Select(p => p.Y).ToList();
                    List <PeakDetectInfo> peakInfo = new List <PeakDetectInfo>();
                    _diamondResult = RamanAnalyzer.Analysis(wl, counts, out peakInfo);

                    if (_diamondResult == ANALYZER_RESULT.ERROR || _diamondResult == ANALYZER_RESULT.ERROR_SPIKE)
                    {
                        break;
                    }

                    if (_diamondResult == ANALYZER_RESULT.NONE)
                    {
                        _peakInfoList.Add(peakInfo);
                        if (factor == 0 || factor == 1)
                        {
                            index++;
                            factor = 1;
                            continue;
                        }
                        else
                        {
                            break;
                        }
                    }
                    else if (_diamondResult == ANALYZER_RESULT.SATURATED)
                    {
                        _peakInfoList.Add(peakInfo);
                        if (factor == 0 || factor == -1)
                        {
                            index--;
                            factor = -1;
                            continue;
                        }
                        else
                        {
                            break;
                        }
                    }
                    else if (_diamondResult == ANALYZER_RESULT.NON_DIAMOND)
                    {
                        if (index >= 2)
                        {
                            _peakInfoList.Clear();
                        }
                        _peakInfoList.Add(peakInfo);
                        break;
                    }
                    else
                    {
                        _peakInfoList.Clear();
                        break;
                    }
                }

                if (_peakInfoList.Count >= 2)
                {
                    _diamondResult = SpectrumAnalyzer.TestAggregate(_peakInfoList);
                }
                _spectrometerPhosResults = _spectroResults;

                watch.Stop();
                long ms = watch.ElapsedMilliseconds;
                Console.WriteLine("spectrum measurement spend: {0}", ms);
                Thread.Sleep(200);

                bw.ReportProgress(progress += step);
                // 3. turn off laser
                if (!_xyzAxesVM.SetLaserOnOff(false))
                {
                    e.Result = new Result(ResultStatus.ERROR, "Failed to turn off the laser");
                    return;
                }

                bw.ReportProgress(progress += step);
                e.Result = new Result(ResultStatus.SUCCESS, null);
            } catch (Exception ex)
            {
                Console.WriteLine("measurementvm exception: " + ex.Message);
                e.Result = new Result(ResultStatus.ERROR, ex.Message);
            }
        }