public PhosResultsViewModel(CamPhosResults camResults, SpectrometerPhosResults spectroResults)
        {
            base.DisplayName        = "PhosResultsViewModel";
            ShowListItemControl     = false;
            _phosImages             = camResults.Images;
            _phosFilteredImages     = camResults.FilteredImages;
            _phosSpectra            = spectroResults.Spectra;
            CurrentPhosItem         = 1;
            CurrentSpectraItem      = 1;
            SaveFolderPath          = Properties.Settings.Default.SaveFolderPath;
            _startTimeStamp         = camResults.StartTimeStamp;
            _spectrumStartTimeStamp = spectroResults.StartTimeStamp;

            CommandSetFolder           = new RelayCommand(param => SetFolder(), cc => _busy == false);
            CommandPreviousPhosItem    = new RelayCommand(param => PreviousPhosItem(), cc => _busy == false);
            CommandNextPhosItem        = new RelayCommand(param => NextPhosItem(), cc => _busy == false);
            CommandPreviousSpectraItem = new RelayCommand(param => PreviousSpectraItem(), cc => _busy == false);
            CommandNextSpectraItem     = new RelayCommand(param => NextSpectraItem(), cc => _busy == false);
            CommandSave    = new RelayCommand(param => Save(), cc => _busy == false);
            CommandSaveAll = new RelayCommand(param => Save(true), cc => _busy == false);

            CommandCalibrate = new RelayCommand(param => Calibrate());

            SpectrumData       = new ObservableDataSource <Point>();
            SmoothSpectrumData = new ObservableDataSource <Point>();
        }
        public PhosResultsViewModel(CamPhosResults camResults, SpectrometerPhosResults spectroResults, List <List <PeakDetectInfo> > peakInfoList, ANALYZER_RESULT diamondResult, List <Tuple <System.Windows.Shapes.Ellipse, TextBlock, Point> > markerList, CamPhosResults camResultsPre)
        {
            base.DisplayName        = "PhosResultsViewModel";
            ShowListItemControl     = false;
            _phosImages             = camResults.Images;
            _phosFilteredImages     = camResults.FilteredImages;
            _phosSpectra            = spectroResults.Spectra;
            NumSpectraItems         = _phosSpectra.Count.ToString();
            CurrentListItem         = 0;
            CurrentPhosItem         = 1;
            CurrentSpectraItem      = 1;
            SaveFolderPath          = Properties.Settings.Default.SaveFolderPath;
            _startTimeStamp         = camResults.StartTimeStamp;
            _spectrumStartTimeStamp = spectroResults.StartTimeStamp;
            PeakInfoList            = peakInfoList;
            DiamondResult           = diamondResult;
            SpectrumIntegrationTime = _phosSpectra[0].IntegrationTime.ToString();
            MarkerList    = markerList;
            CamResultsPre = camResultsPre.Images;

            Width  = CamResultsPre[0].Image.Width;
            Height = CamResultsPre[0].Image.Height;

            CommandSetFolder           = new RelayCommand(param => SetFolder(), cc => _busy == false);
            CommandPreviousPhosItem    = new RelayCommand(param => PreviousPhosItem(), cc => _busy == false);
            CommandNextPhosItem        = new RelayCommand(param => NextPhosItem(), cc => _busy == false);
            CommandPreviousSpectraItem = new RelayCommand(param => PreviousSpectraItem(), cc => _busy == false);
            CommandNextSpectraItem     = new RelayCommand(param => NextSpectraItem(), cc => _busy == false);
            CommandSave    = new RelayCommand(param => Save(), cc => _busy == false);
            CommandSaveAll = new RelayCommand(param => Save(true), cc => _busy == false);

            CommandCalibrate = new RelayCommand(param => Calibrate());

            SpectrumData       = new ObservableDataSource <Point>();
            SmoothSpectrumData = new ObservableDataSource <Point>();

            InitializeColorLegend();
        }
        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);
            }
        }
        public PhosResultsViewModel(List <CamPhosResults> camResList, List <SpectrometerPhosResults> specResList, List <List <List <PeakDetectInfo> > > peakInfoListList, List <ANALYZER_RESULT> diamondResList, List <Tuple <System.Windows.Shapes.Ellipse, TextBlock, Point> > markerList, CamPhosResults camResultsPre, bool mappingMeasure = false, System.Windows.Shapes.Rectangle rect = null)
        {
            base.DisplayName    = "PhosResultsViewModelBatchMeasurement";
            ShowListItemControl = false;
            CamResList          = camResList;
            SpecResList         = specResList;
            PeakInfoListList    = peakInfoListList;
            DiamondResList      = diamondResList;
            MarkerList          = markerList;
            CamResultsPre       = camResultsPre.Images;
            this.mappingMeasure = mappingMeasure;
            RectMark            = rect;

            Width  = CamResultsPre[0].Image.Width;
            Height = CamResultsPre[0].Image.Height;

            _phosImages         = CamResList[0].Images;
            _phosFilteredImages = CamResList[0].FilteredImages;
            _phosSpectra        = SpecResList[0].Spectra;
            DiamondResult       = DiamondResList[0];
            PeakInfoList        = peakInfoListList[0];

            CurrentListItem         = 1;
            CurrentPhosItem         = 1;
            CurrentSpectraItem      = 1;
            SaveFolderPath          = Properties.Settings.Default.SaveFolderPath;
            _startTimeStamp         = CamResList[0].StartTimeStamp;
            _spectrumStartTimeStamp = SpecResList[0].StartTimeStamp;
            SpectrumIntegrationTime = _phosSpectra[0].IntegrationTime.ToString();

            CommandSetFolder           = new RelayCommand(param => SetFolder(), cc => _busy == false);
            CommandPreviousPhosItem    = new RelayCommand(param => PreviousPhosItem(), cc => _busy == false);
            CommandNextPhosItem        = new RelayCommand(param => NextPhosItem(), cc => _busy == false);
            CommandPreviousSpectraItem = new RelayCommand(param => PreviousSpectraItem(), cc => _busy == false);
            CommandNextSpectraItem     = new RelayCommand(param => NextSpectraItem(), cc => _busy == false);
            CommandSave    = new RelayCommand(param => Save(), cc => _busy == false);
            CommandSaveAll = new RelayCommand(param => Save(true), cc => _busy == false);

            CommandPreviousListItem = new RelayCommand(param => PreviousListItem(), cc => _busy == false);
            CommandNextListItem     = new RelayCommand(param => NextListItem(), cc => _busy == false);

            CommandCalibrate = new RelayCommand(param => Calibrate(), cc => mappingMeasure == false);

            SpectrumData       = new ObservableDataSource <Point>();
            SmoothSpectrumData = new ObservableDataSource <Point>();

            InitializeColorLegend();
        }