Example #1
0
        /// <summary>
        /// 残差2乗和を求めてそれを返します。
        /// </summary>
        /// <param name="data">測定データ.</param>
        /// <param name="reference">(一般には複数の)参照データ.</param>
        /// <returns></returns>
        static decimal CulculateResidual(bool with_offset, IList <decimal> data, params IList <decimal>[] references)        // C# 6.0 で,params引数に配列型以外も使えるようになった.
        {
            // 2.最適値なゲイン係数(+オフセット値)を求める
            var gains = GetOptimizedGains(with_offset, data, references);

            // 3.残差を求める
            var residual = EqualIntervalData.GetTotalSquareResidual(data, gains.ToArray(), references);             // 残差2乗和

            Trace.WriteLine($"residual = {residual}");

            return(residual);
        }
Example #2
0
        FitForOneShiftResult DecideShift(EqualIntervalData targetData, ScanParameter originalParameter)
        {
            var gains = new Dictionary <decimal, Vector <double> >();
            Dictionary <decimal, decimal> residuals = new Dictionary <decimal, decimal>();
            var            best_fit_result          = new FitForOneShiftResult();
            List <decimal> shiftList = new List <decimal>();

            // 1回目
            for (int m = -6; m < 7; m++)
            {
                shiftList.Add(0.5M * m);                 // とりあえず。
            }
            Trace.WriteLine($"SearchShift START!! {DateTime.Now:O}  [{Thread.CurrentThread.ManagedThreadId}]");
            best_fit_result = SearchBestShift(shiftList, best_fit_result);
            var best_shift = best_fit_result.Shift;

            Trace.WriteLine($"SearchShift Completed!! {DateTime.Now:O}  [{Thread.CurrentThread.ManagedThreadId}]");
            Trace.WriteLine($"シフト値は {best_shift} がよさそうだよ!");

            // 2回目
            shiftList.Clear();
            for (int i = 1; i < 5; i++)
            {
                shiftList.Add(best_shift + 0.1M * i);
                shiftList.Add(best_shift - 0.1M * i);
            }
            return(SearchBestShift(shiftList, best_fit_result));

            #region ローカル関数

            #region **与えられたシフト量から最適なものを探す(SearchBestShift)
            FitForOneShiftResult SearchBestShift(
                IEnumerable <decimal> shiftCandidates,
                FitForOneShiftResult previousResult)
            {
                var best_result = previousResult;

                // ※たぶん,メンバ変数にする必要がある.
                var    _cancellation_token = new CancellationToken();
                object lockObject          = new object();

                var loopResult = Parallel.ForEach <decimal, FitForOneShiftResult>(
                    shiftCandidates,
                    new ParallelOptions {
                    CancellationToken = _cancellation_token
                },
                    () => best_result,
                    (shift, state, best) =>
                {
                    return(FitForOneShift(shift));
                },
                    (result) => {
                    lock (lockObject)
                    {
                        if (!best_result.Residual.HasValue || best_result.Residual.Value > result.Residual.Value)
                        {
                            best_result = result;
                        }
                    }
                }
                    );

                return(best_result);

                #region ローカル関数

                #region ***1つのシフト量に対してフィッティングを行う(FitForOneShift)

                // とりあえず同期版を使う.
                // IO待ちのメソッドではないので,asyncにしない方がよい?

                FitForOneShiftResult FitForOneShift(decimal shift)
                {
                    Trace.WriteLine($"shift : {shift}         {DateTime.Now:O}  [{Thread.CurrentThread.ManagedThreadId}]");

                    var shifted_parameter = originalParameter.GetShiftedParameter(shift);

                    // ここを非同期にすると,制御が返らなくなる?
                    // シフトされた参照スペクトルを読み込む。
                    var standards = LoadShiftedStandardsData(ReferenceSpectra, shifted_parameter);

                    // フィッティングを行い、
                    //Trace.WriteLine($"Cycle {cycle}");
                    var gain = GetOptimizedGains(WithOffset, targetData, standards.ToArray());

                    //gains.Add(shift, );
                    for (int j = 0; j < ReferenceSpectra.Count; j++)
                    {
                        Trace.WriteLine($"    {ReferenceSpectra[j].Name} : {gain[j]}        [{Thread.CurrentThread.ManagedThreadId}]");
                    }
                    Trace.WriteLine($"    Const : {gain[ReferenceSpectra.Count]}        [{Thread.CurrentThread.ManagedThreadId}]");

                    // 残差を取得する。
                    var residual = EqualIntervalData.GetTotalSquareResidual(targetData, gain.ToArray(), standards.ToArray());                     // 残差2乗和

                    //residuals.Add(shift, residual);
                    Trace.WriteLine($"residual = {residual}        [{Thread.CurrentThread.ManagedThreadId}]");

                    return(new FitForOneShiftResult {
                        Gain = gain, Shift = shift, Residual = residual
                    });
                }

                #endregion

                #endregion
            }

            #endregion

            #endregion
        }