public async Task FitSingleProfile(FittingProfile profile) { var d_data = WideScan.GetRestrictedData(profile.RangeBegin, profile.RangeEnd).Differentiate(_differentialWindow); var fitting_results = new FittingProfile.FittingResult(); // キーはサイクル数. EqualIntervalData target_data = new EqualIntervalData(); // 1.まず,フィッティングの計算を行う. { #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を考慮しない。 target_data = d_data.Data; //fitting_tasks.Add(i, profile.FitOneCycle(i, target_data[i], d_data.Parameter)); fitting_results = profile.FitOneCycle(-1, target_data, d_data.Parameter); } // 2.その後に,チャート出力を行う? Gnuplot charts = await Output(d_data.Parameter, profile, target_data, fitting_results); // pltファイルも出力してみる。 using (var writer = new StreamWriter(GetCsvFileName(profile.Name, -1) + ".plt")) { await charts.OutputPltFileAsync(writer); } // チャートを描画する。 await charts.Draw(); }
/// <summary> /// ファイルからスペクトルを読み込み,指定されたプロファイルの参照データとします. /// </summary> /// <param name="idFileName"></param> /// <param name="profile"></param> /// <returns></returns> public async Task AddReferenceSpectrumAsync(string idFileName, FittingProfile profile) { var dir = Path.GetDirectoryName(idFileName); if ((await IdFile.CheckTypeAsync(idFileName)) == DataType.WideScan) { // OK profile.ReferenceSpectra.Add(new ReferenceSpectrum { DirectoryName = dir }); } else { //var error_message = new SimpleMessage(this) { Message = "WideScanじゃないとだめだよ!" }; //Messenger.Default.Send(this, error_message); } }
// とりあえず分けた. /// <summary> /// profileで指定した範囲に最適なROIを探し出します. /// </summary> /// <param name="profile"></param> protected ROISpectra FindROI(FittingProfile profile) { // profileがBaseROIを持つのではなく,ここでBaseとなるROIを決定するようにしてみた. // ★一応,範囲から推測するのをベースにするけど, // ★ROIの名前からでも指定できるようにするのがいいのでは? // ProfileのRangeを包含するROIを探す. var suitable_roi_list = ROISpectraCollection.Where(roi => roi.Parameter.Start <= profile.RangeBegin && roi.Parameter.Stop >= profile.RangeEnd); if (suitable_roi_list.Count() == 0) { var message = $"{profile.Name}に対応する測定データがありませんでした。エネルギー範囲を確認して下さい。 {profile.RangeBegin} - {profile.RangeEnd}"; // 終了.並列実行することがあるので,例外を発生させる. throw new MyException(message); } return(suitable_roi_list.OrderBy(roi => roi.Parameter.Step).First()); }
public void LoadFrom(StreamReader reader) { var doc = XDocument.Load(reader); var root = doc.Root; if (root.Name == ELEMENT_NAME) { this.OutputDestination = (string)root.Attribute(OUTPUTDESTINATION_ATTRIBUTE); var chart_format = (string)root.Attribute(CHARTFORMAT_ATTRIBUTE); if (!string.IsNullOrEmpty(chart_format)) { this.ChartFormat = (ChartFormat)Enum.Parse(typeof(ChartFormat), chart_format); } } FittingProfiles.Clear(); foreach (var profile in root.Element(PROFILES_ELEMENT).Elements(FittingProfile.ELEMENT_NAME)) { this.FittingProfiles.Add(FittingProfile.LoadProfile(profile)); } }
// (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)); }
// (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 }
public static FittingProfile LoadProfile(XElement profileElement) { var profile = new FittingProfile(); profile.Name = (string)profileElement.Attribute(NAME_ATTRIBUTE); profile.RangeBegin = (decimal)profileElement.Attribute(ENERGYBEGIN_ATTRIBUTE); profile.RangeEnd = (decimal)profileElement.Attribute(ENERGYEND_ATTRIBUTE); profile.WithOffset = (bool)profileElement.Attribute(WITHOFFSET_ATTRIBUTE); var energy_shift = (decimal?)profileElement.Attribute(ENERGYSHIFT_ATTRIBUTE); if (profile.FixEnergyShift = energy_shift.HasValue) { profile.FixedEnergyShift = energy_shift.Value; } profile.ReferenceSpectra.Clear(); foreach (var reference in profileElement.Element(REFERENCES_ELEMENT).Elements(REFERENCE_ELEMENT)) { profile.ReferenceSpectra.Add(new ReferenceSpectrum { DirectoryName = (string)reference.Attribute(DIRECTORY_ATTRIBUTE) }); } profile.FixedSpectra.Clear(); foreach (var reference in profileElement.Element(REFERENCES_ELEMENT).Elements(FIXED_REFERENCES_ELEMENT)) { profile.FixedSpectra.Add(new FixedSpectrum { DirectoryName = (string)reference.Attribute(DIRECTORY_ATTRIBUTE), Gain = (decimal)reference.Attribute(GAIN_ATTRIBUTE), Shift = (decimal)reference.Attribute(SHIFT_ATTRIBUTE) }); } return(profile); }
// 指定したプロファイルを削除する? public void RemoveFittingProfile(FittingProfile profile) { FittingCondition.FittingProfiles.Remove(profile); }
/// <summary> /// 具体的なチャートの設定を行います. /// </summary> /// <param name="cycle"></param> /// <param name="result"></param> /// <param name="profile"></param> /// <param name="outputConvolution"></param> /// <returns></returns> public Gnuplot ConfigureChart(FittingProfile.FittingResult result, FittingProfile profile, bool outputConvolution, int cycle = -1) { string chart_ext = string.Empty; switch (FittingCondition.ChartFormat) { case ChartFormat.Png: chart_ext = ".png"; break; case ChartFormat.Svg: chart_ext = ".svg"; break; } var chart_destination = Path.Combine(FittingCondition.OutputDestination, $"{profile.Name}{(cycle >= 0 ? string.Format("_{0}", cycle) : string.Empty)}{chart_ext}"); #region チャート設定 var gnuplot = new Gnuplot { Format = FittingCondition.ChartFormat, Width = 800, Height = 600, FontScale = 1.6, Destination = chart_destination, XTitle = "Kinetic Energy / eV", YTitle = "dN(E)/dE", Title = (cycle >= 0 ? $"Cycle {cycle} , " : string.Empty) + $"Shift {result.Shift} eV" }; var source_csv = GetCsvFileName(profile.Name, cycle); gnuplot.DataSeries.Add(new LineChartSeries { SourceFile = source_csv, XColumn = 1, YColumn = 2, Title = "data", Style = new LineChartSeriesStyle(LineChartStyle.Lines) { Style = new LinePointStyle { LineColor = "#FF0000", LineWidth = 3, } } }); var reference_names = profile.ReferenceSpectra.Select(r => r.Name).ToList(); for (int j = 0; j < reference_names.Count; j++) { gnuplot.DataSeries.Add(new LineChartSeries { SourceFile = source_csv, XColumn = 1, YColumn = j + 3, Title = $"{result.Gains[j].ToString("f3")} * {reference_names[j]}", Style = new LineChartSeriesStyle(LineChartStyle.Lines) { Style = new LinePointStyle { LineColorIndex = j, LineWidth = 2, } } }); } if (outputConvolution) { gnuplot.DataSeries.Add(new LineChartSeries { SourceFile = source_csv, XColumn = 1, YColumn = reference_names.Count + 3, Title = "Convolution", Style = new LineChartSeriesStyle(LineChartStyle.Lines) { Style = new LinePointStyle { LineColor = "#0000FF", LineWidth = 3, } } }); } #endregion gnuplot.PreConfigureAxis(); return(gnuplot); }
// (0.1.0)1つのProfileについてのみフィッティングを行う. #region *1つのProfileに対してフィッティングを行う(FitSingleProfile) public async Task FitSingleProfile(FittingProfile profile) { // profileがBaseROIを持つのではなく,ここでBaseとなるROIを決定するようにしてみた. // ★一応,範囲から推測するのをベースにするけど, // ★ROIの名前からでも指定できるようにするのがいいのでは? // ProfileのRangeを包含するROIを探す. var baseROI = FindROI(profile); var d_data = baseROI.Restrict(profile.RangeBegin, profile.RangeEnd) .Differentiate(3); //var fitting_tasks = new Dictionary<int, Task<FittingProfile.FittingResult>>(); var fitting_results = new Dictionary <int, FittingProfile.FittingResult>(); // キーはサイクル数. Dictionary <int, EqualIntervalData> target_data = new Dictionary <int, EqualIntervalData>(); // 1.まず,フィッティングの計算を行う. foreach (int i in FittingCondition.TargetCycles) { #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を考慮しない。 target_data[i] = d_data.Data[i]; fitting_results.Add(i, profile.FitOneCycle(i, target_data[i], d_data.Parameter)); } // 2.その後に,チャート出力を行う? //Dictionary<int, Gnuplot> charts = new Dictionary<int, Gnuplot>(); Dictionary <int, Task <Gnuplot> > gnuplot_tasks = new Dictionary <int, Task <Gnuplot> >(); foreach (int i in FittingCondition.TargetCycles) { gnuplot_tasks[i] = Output(i, d_data.Parameter, profile, target_data[i], fitting_results[i]); } await Task.WhenAll(gnuplot_tasks.Values.ToArray()); Dictionary <int, Gnuplot> charts = new Dictionary <int, Gnuplot>(); foreach (var task in gnuplot_tasks) { charts[task.Key] = task.Value.Result; } // 全てのchartで共通の軸範囲を使用する. Range x_range = Range.Union(charts.Select(gnuplot => gnuplot.Value.XAxis.Range).ToArray()); Range y_range = Range.Union(charts.Select(gnuplot => gnuplot.Value.YAxis.Range).ToArray()); //Range x_range = Range.Union(charts.Select(gnuplot => gnuplot.Value.Result.XAxis.Range).ToArray()); //Range y_range = Range.Union(charts.Select(gnuplot => gnuplot.Value.Result.YAxis.Range).ToArray()); Parallel.ForEach(charts.Keys, async(i) => { charts[i].DefineXAxis(x_range); charts[i].DefineYAxis(y_range); //charts[i].Result.SetXAxis(x_range); //charts[i].Result.SetYAxis(y_range); // pltファイルも出力してみる。 using (var writer = new StreamWriter(GetCsvFileName(i, profile.Name) + ".plt")) { await charts[i].OutputPltFileAsync(writer); //await charts[i].Result.OutputPltFileAsync(writer); } // チャートを描画する。 await charts[i].Draw(); //await charts[i].Result.Draw(); } ); }