Exemple #1
0
        // (0.2.0)
        /// <summary>
        /// 指定したディレクトリのparaファイルを読み込み,Scanparameterオブジェクトを生成します.
        /// </summary>
        /// <param name="directory"></param>
        /// <returns></returns>
        public static async Task <ScanParameter> GenerateAsync(string directory)
        {
            var parameter = new ScanParameter();
            await parameter.LoadFromAsync(directory);

            return(parameter);
        }
Exemple #2
0
        public static ScanParameter Generate(string directory)
        {
            var parameter = new ScanParameter();

            parameter.LoadFrom(directory);
            return(parameter);
        }
Exemple #3
0
        private async Task OutputFittedCsv(StreamWriter writer, ScanParameter originalParameter, EqualIntervalData targetData, FittingProfile.FittingResult result, bool outputConvolution)
        {
            for (int k = 0; k < originalParameter.PointsCount; k++)
            {
                List <string> cols = new List <string>();

                // 0列: エネルギー値
                cols.Add((originalParameter.Start + k * originalParameter.Step + result.Shift).ToString("f2"));

                // 1列: 測定データ
                cols.Add(targetData[k].ToString("f3"));

                // 2~N列: 各成分(標準データ×ゲイン)
                decimal conv = 0;
                for (int j = 0; j < result.Standards.Count; j++)
                {
                    var intensity = result.GetGainedStandard(j, k);
                    conv += intensity;
                    cols.Add(intensity.ToString("f3"));
                }

                // 最終列: 成分の総和
                if (outputConvolution)
                {
                    cols.Add(conv.ToString("f3"));
                }

                await writer.WriteLineAsync(string.Join(",", cols));
            }
        }
Exemple #4
0
        // とりあえず.
        public void LoadFrom(string directory)
        {
            // パラメータを読み込む。
            _scanParameter = ScanParameter.Generate(directory);

            // データを読み込む。
            using (var reader = new BinaryReader(new FileStream(Path.Combine(directory, "data"), FileMode.Open, FileAccess.Read)))
            {
                _data = EqualIntervalData.Generate(reader);
            }
        }
Exemple #5
0
        /// <summary>
        /// 与えられたパラメータによりシフトされたデータ列を返します.
        /// </summary>
        /// <param name="parameter">エネルギー軸の範囲の情報だけを用いています.</param>
        /// <param name="m"></param>
        /// <returns></returns>
        public async Task <IList <decimal> > GetDataAsync(ScanParameter parameter, int m, decimal shift = 0, decimal gain = 1)
        {
            if (m <= 0)
            {
                throw new ArgumentException("mには正の値を与えて下さい.");
            }
            var ws = await WideScan.GenerateAsync(this.DirectoryName);

            return(ws.Differentiate(m)
                   .GetInterpolatedData(parameter.Start - shift, parameter.Step, parameter.PointsCount)
                   .Select(d => d * ws.Parameter.NormalizationGain / parameter.NormalizationGain * gain).ToList());
        }
Exemple #6
0
        public async Task LoadFromAsync(string directory)
        {
            // パラメータを読み込む。
            _scanParameter = await ScanParameter.GenerateAsync(directory);


            // データを読み込む。
            using (var reader = new BinaryReader(new FileStream(Path.Combine(directory, "data"), FileMode.Open, FileAccess.Read)))
            {
                _data = await EqualIntervalData.GenerateAsync(reader);
            }
            //Loaded(this, EventArgs.Empty);
        }
Exemple #7
0
        public async Task LoadFromAsync(string directory)
        {
            using (var reader = new StreamReader(new FileStream(Path.Combine(directory, "para"), FileMode.Open, FileAccess.Read)))
            {
                while (reader.Peek() > -1)
                {
                    var line = await reader.ReadLineAsync();

                    var cols = line.Split(new string[] { "  " }, StringSplitOptions.RemoveEmptyEntries);
                    if (cols.Count() > 1)
                    {
                        switch (cols[0])
                        {
                        case "$AP_SPC_WSTART":
                            Start = Convert.ToDecimal(cols[1]);
                            break;

                        case "$AP_SPC_WSTOP":
                            Stop = Convert.ToDecimal(cols[1]);
                            break;

                        case "$AP_SPC_WSTEP":
                            Step = Convert.ToDecimal(cols[1]);
                            break;
                        // とりあえず無視する。
                        //case "$AP_SPC_WPOINTS":
                        //	_scanParameter.noPoints = Convert.ToInt32(cols[1]);
                        //	break;

                        // 正規化に関しては、とりあえず電流とdwellだけ考慮する。Tiltや加速電圧はあとで考える。
                        case "$AP_PCURRENT":
                            Current = ScanParameter.ConvertPressure(cols[1]);
                            break;

                        case "$AP_SPC_WDWELL":
                            Dwell = Convert.ToDecimal(cols[1]) * 1e-3M;
                            break;

                        case "$AP_SPC_W_XSHIFT":
                            XShift = Convert.ToDecimal(cols[1]);
                            break;

                        case "$AP_STGTILT":
                            Tilt = Convert.ToDouble(cols[1]);
                            break;
                        }
                    }
                }
            }
        }
Exemple #8
0
        // (0.1.0)メソッド名をFitからOutputに変更.というか,これどこにおけばいいのかな?
        private async Task <Gnuplot> Output(
            ScanParameter originalParameter,
            FittingProfile profile,
            EqualIntervalData target_data,
            FittingProfile.FittingResult result)
        {
            // フィッティングした結果をチャートにする?
            // ★とりあえずFixedなデータは表示しない。

            bool output_convolution = result.Standards.Count > 1;

            // それには、csvを出力する必要がある。
            //string fitted_csv_path = Path.Combine(FittingCondition.OutputDestination, $"{FittingCondition.Name}_{layer}.csv");
            using (var csv_writer = new StreamWriter(GetCsvFileName(profile.Name)))
            {
                await OutputFittedCsv(csv_writer, originalParameter, target_data, result, output_convolution).ConfigureAwait(false);
            }

            // チャート出力の準備?
            return(ConfigureChart(result, profile, output_convolution));
        }
Exemple #9
0
        // (0.1.0)メソッド名をFitからOutputに変更.というか,これどこにおけばいいのかな?
        #region *CSVを出力して,グラフ描画の準備を行う(Output)
        /// <summary>
        /// フィッティングした結果から,チャートの出力を設定します.
        /// </summary>
        /// <param name="cycle"></param>
        /// <param name="originalParameter"></param>
        /// <param name="profile"></param>
        /// <param name="target_data"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        private async Task <Gnuplot> Output(
            int cycle,
            ScanParameter originalParameter,
            FittingProfile profile,
            EqualIntervalData target_data,
            FittingProfile.FittingResult result)
        {
            // フィッティングした結果をチャートにする?
            // ★とりあえずFixedなデータは表示しない。
            Trace.WriteLine($"Let's start outputting! cycle{cycle} {DateTime.Now}     [{Thread.CurrentThread.ManagedThreadId}]");
            bool output_convolution = result.Standards.Count > 1;

            // それには、csvを出力する必要がある。
            using (var csv_writer = new StreamWriter(GetCsvFileName(cycle, profile.Name)))
            {
                await OutputFittedCsv(csv_writer, originalParameter, target_data, result, output_convolution);
            }
            Trace.WriteLine($"CSV output Completed! cycle{cycle} {DateTime.Now}     [{Thread.CurrentThread.ManagedThreadId}]");

            // チャート出力の準備?
            return(ConfigureChart(result, profile, output_convolution, cycle));

            #region こうすると,1024バイトほど書き込んだところで落ちる.
            // どう違うのかはよくわかっていない.

            /*
             * Gnuplot chartConfiguration;
             * // chartConfigurationを構成して返す処理とcsv出力処理が入り交じっているので注意.(こういう書き方しか思いつかなかった.)
             * using (var csv_writer = new StreamWriter(GetCsvFileName(cycle, profile.Name)))
             * {
             *      //var outputCsvTask = OutputFittedCsv(csv_writer, originalParameter, target_data, result, output_convolution);
             *      //chartConfiguration = ConfigureChart(cycle, result, profile, output_convolution);
             *      //await outputCsvTask;
             *      await OutputFittedCsv(csv_writer, originalParameter, target_data, result, output_convolution);
             * }
             * return chartConfiguration;
             */
            #endregion
        }
Exemple #10
0
        // (0.3.0)Tiltを考慮.
        #region *パラメータを読み込む(ReadParaPeakAsync)
        /// <summary>
        /// para.peakファイルを読み込みます。
        /// </summary>
        /// <param name="directory"></param>
        /// <returns></returns>
        protected async Task <ROISpectra[]> ReadParaPeakAsync(string directory)
        {
            // $AP_DEP_ROI_NOFEXE  6

            /*
             * $AP_DEP_ROI_EXEMOD  1 1
             * $AP_DEP_ROI_NAME  1 Ti
             * $AP_DEP_ROI_START  1 404.00
             * $AP_DEP_ROI_STOP  1 431.00
             * $AP_DEP_ROI_STEP  1 0.50
             * $AP_DEP_ROI_POINTS  1 55
             * $AP_DEP_ROI_DWELL  1 200
             * $AP_DEP_ROI_SWEEPS  1 5
             * $AP_DEP_ROI_ACQRSF  1 0.414
             */

            //ROIParameters[0] = new ROIParameter();
            ROISpectra[] roi_spectra = null;
            decimal?     current     = null;
            double?      tilt        = null;

            using (var reader = new StreamReader(new FileStream(Path.Combine(directory, "para"), FileMode.Open, FileAccess.Read)))
            {
                while (reader.Peek() > -1)
                {
                    var line = await reader.ReadLineAsync();

                    var cols = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                    if (cols.Count() > 1)
                    {
                        switch (cols[0])
                        {
                        case "$AP_DEP_CYCLES":
                            Cycles = Convert.ToInt32(cols[1]);
                            break;

                        case "$AP_PCURRENT":
                            current = ScanParameter.ConvertPressure(cols[1], cols[2]);
                            break;

                        case "$AP_STGTILT":
                            tilt = Convert.ToDouble(cols[1]);
                            break;

                        case "$AP_DEP_ROI_NOFEXE":
                            int count = Convert.ToInt32(cols[1]);
                            roi_spectra = new ROISpectra[count];
                            for (int i = 0; i < count; i++)
                            {
                                // ここで各要素を初期化しておく。
                                roi_spectra[i] = new ROISpectra();
                            }
                            break;
                            //goto SCAN_ROI;  // switch内でループから脱出するための黒魔術。
                        }
                    }
                }
            }

            if (roi_spectra == null)
            {
                throw new Exception("para.peakファイルに $AP_DEP_ROI_NOFEXEキーがありませんでした。");
            }
            // roi_parametersが初期化されていることを保証するために、ループを2つに分ける。
            //SCAN_ROI:

            int ch;

            using (var reader = new StreamReader(new FileStream(Path.Combine(directory, "para.peak"), FileMode.Open, FileAccess.Read)))
            {
                while (reader.Peek() > -1)
                {
                    var line = reader.ReadLine();
                    var cols = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                    if (cols.Count() > 1)
                    {
                        switch (cols[0])
                        {
                        case "$AP_DEP_ROI_NAME":
                            ch = Convert.ToInt32(cols[1]) - 1;
                            roi_spectra[ch].Name = cols[2];
                            break;

                        case "$AP_DEP_ROI_START":
                            ch = Convert.ToInt32(cols[1]) - 1;
                            roi_spectra[ch].Parameter.Start = Convert.ToDecimal(cols[2]);
                            break;

                        case "$AP_DEP_ROI_STOP":
                            ch = Convert.ToInt32(cols[1]) - 1;
                            roi_spectra[ch].Parameter.Stop = Convert.ToDecimal(cols[2]);
                            break;

                        case "$AP_DEP_ROI_STEP":
                            ch = Convert.ToInt32(cols[1]) - 1;
                            roi_spectra[ch].Parameter.Step = Convert.ToDecimal(cols[2]);
                            break;

                        //case "$AP_DEP_ROI_POINTS":
                        //	ch = Convert.ToInt32(cols[1]) - 1;
                        //	ROIParameters[ch].noPoints = Convert.ToInt32(cols[2]);
                        //	break;
                        case "$AP_DEP_ROI_DWELL":
                            ch = Convert.ToInt32(cols[1]) - 1;
                            roi_spectra[ch].Parameter.Dwell = Convert.ToInt32(cols[2]) * 1e-3M;
                            // ここでcurrentを設定する。
                            roi_spectra[ch].Parameter.Current = current.Value;                                // HasValueでないことは想定していない。
                            // ※AP_STGTILTがAP_DEP_ROI_NOFEXEより後に出てくるので,ここでは値が設定されていない!
                            roi_spectra[ch].Parameter.Tilt = tilt.Value;                                      // HasValueでないことは想定していない。
                            break;
                        }
                    }
                }
            }

            return(roi_spectra);
        }
Exemple #11
0
        /// <summary>
        /// シフトを考慮した固定参照データを読み込みます.
        /// </summary>
        /// <param name="references"></param>
        /// <param name="parameter"></param>
        /// <returns></returns>
        static async Task <List <List <decimal> > > LoadShiftedFixedStandardsData(ICollection <FixedSpectrum> references, ScanParameter parameter)
        {
            List <List <decimal> > standards = new List <List <decimal> >();

            foreach (var item in references)
            {
                var ws = await WideScan.GenerateAsync(item.DirectoryName);

                standards.Add(
                    ws.Differentiate(3)
                    .GetInterpolatedData(parameter.Start - item.Shift, parameter.Step, parameter.PointsCount)
                    .Select(d => d * ws.Parameter.NormalizationGain / parameter.NormalizationGain * item.Gain).ToList()
                    );
            }
            return(standards);
        }
Exemple #12
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
        }
Exemple #13
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="cycle">対象サイクル.デバッグ出力にしか使用していません.</param>
        /// <param name="data"></param>
        /// <param name="originalParameter"></param>
        /// <returns></returns>
        //public async Task<FittingResult> FitOneCycle(int cycle, EqualIntervalData data, ScanParameter originalParameter)
        public FittingResult FitOneCycle(int cycle, EqualIntervalData data, ScanParameter originalParameter)
        {
            #region  固定参照スペクトルを取得する。(一時的にコメントアウト中)

            /*
             * List<decimal> fixed_data = new List<decimal>();
             * if (FixedSpectra.Count > 0)
             * {
             *      var v_data = await FixedSpectra.ForEachAsync(
             *              async sp => await sp.GetShiftedDataAsync(d_data.Parameter, 3), 10);
             *
             *      for (int j = 0; j < v_data.First().Count; j++)
             *      {
             *              fixed_data.Add(v_data.Sum(one => one[j]));
             *      }
             * }
             */
            #endregion


            /// フィッティング対象となるデータ。すなわち、もとのデータからFixされた分を差し引いたデータ。
            //var target_data = fixed_data.Count > 0 ? data.Substract(fixed_data) : data;
            // なんだけど、とりあえずはFixedを考慮しない。
            var target_data = data;


            if (!FixEnergyShift)
            {
                #region A.最適なエネルギーシフト量を見つける場合

                Trace.WriteLine($"Cycle {cycle} START!! {DateTime.Now}  [{Thread.CurrentThread.ManagedThreadId}]");

                var best_fitting_result = DecideShift(target_data, originalParameter);
                var best_shift          = best_fitting_result.Shift;

                Trace.WriteLine($" {cycle} 本当に最適なシフト値は {best_shift} だよ!");
                Trace.WriteLine($"Cycle {cycle} END!! {DateTime.Now}  [{Thread.CurrentThread.ManagedThreadId}]");



                // シフトされた参照スペクトルを読み込む。
                var best_shifted_parameter = originalParameter.GetShiftedParameter(best_shift);
                //var best_standards = LoadShiftedStandardsDataAsync(ReferenceSpectra, best_shifted_parameter);
                var best_standards = LoadShiftedStandardsData(ReferenceSpectra, best_shifted_parameter);
                var best_gain      = best_fitting_result.Gain;

                return(new FittingResult {
                    Shift = best_shift, Gains = best_gain.Select(d => Convert.ToDecimal(d)).ToArray(), Standards = best_standards
                });

                #endregion
            }
            else
            {
                #region B.エネルギーシフト量を自分で与える場合

                var shifted_parameter = originalParameter.GetShiftedParameter(FixedEnergyShift);

                // シフトされた参照スペクトルを読み込む。
                var standards = LoadShiftedStandardsData(ReferenceSpectra, shifted_parameter);

                // フィッティングを行い、
                Trace.WriteLine($"Cycle {cycle}");
                var gains = GetOptimizedGains(WithOffset, target_data, standards.ToArray());
                for (int j = 0; j < ReferenceSpectra.Count; j++)
                {
                    Trace.WriteLine($"    {ReferenceSpectra[j].Name} : {gains[j]}");
                }
                Trace.WriteLine($"    Const : {gains[ReferenceSpectra.Count]}");

                return(new FittingResult
                {
                    Shift = FixedEnergyShift,
                    Standards = standards,
                    Gains = gains.Select(d => Convert.ToDecimal(d)).ToArray()
                });

                #endregion
            }

            // 出力は呼び出し元で行う!
        }
Exemple #14
0
 public ROISpectra()
 {
     Parameter = new ScanParameter();
 }
Exemple #15
0
 /// <summary>
 /// 与えられたパラメータによりシフトされたデータ列を返します.
 /// </summary>
 /// <param name="parameter">エネルギー軸の範囲の情報だけを用いています.</param>
 /// <param name="m"></param>
 /// <returns></returns>
 public async Task <IList <decimal> > GetShiftedDataAsync(ScanParameter parameter, int m)
 {
     return(await GetDataAsync(parameter, m, Shift, Gain));
 }