"""
optimize_peakfit_mfモジュール
概要:
ピークフィッティングの最適化に関連する関数を提供するモジュールです。
詳細説明:
外部コマンド実行の設定、パラメータの初期化、フィッティングプロセスのセットアップ、
データの読み込み、関数値の計算など、一連のフィッティングワークフローをサポートします。
このモジュールは、主にtklibライブラリのtkFit_mxyクラスやtkoptimize_flexモジュール、
およびpeakfitモジュールと連携して動作します。
関連リンク:
:doc:`optimize_peakfit_mf_usage`
"""
import os
import platform
import re
import time
from datetime import datetime
import numpy as np
from numpy import log, abs, sqrt, exp
from scipy import interpolate
import pandas as pd
from matplotlib import pyplot as plt
from functools import lru_cache
from tklib.tkparams import tkParams
from tklib.tksci.tkFit_mxy_flex import tkFit_mxy
from tklib.tksci.tkFit_lib import conv_input, save_data, add_history
from tklib.tksci.tkFit_object import save_fit_config, read_fit_config_from_file
import tklib.tksci.tkoptimize_flex as opt
import peakfit as omodel
[ドキュメント]
def initialize_minimize_func(app):
"""
外部コマンド実行に必要なグローバル設定を初期化します。
詳細説明:
`app`オブジェクトから設定を読み込み、`app.config_cmd`に設定します。
主に外部スクリプト(`config.script`)のパスなどを設定します。
現在はプラットフォームに依存しない設定がハードコードされていますが、
コメントアウトされた部分にはOSごとの`atlas_cmd`などの設定例があります。
:param app: アプリケーションのグローバル設定を保持するオブジェクト。
:type app: object
:returns: なし
:rtype: None
"""
globals()["app"] = app
cfg = app.cfg
if app.get("config_cmd", None) is None: app.config_cmd = tkParams()
config = app.config_cmd
os = platform.system()
config.script = 'mobility_polyOS240312.py'
'''
if os == 'Linux':
config.atlas_cmd = cfg.atlas_cmd_linux #'/home/share/sedatools/bin/deckbuild'
config.atlas_options = cfg.atlas_options_linux # '-run -ascii'
elif os == 'Windows':
config.atlas_cmd = cfg.atlas_cmd_win # 'c:/sedatools/exe/deckbuild'
config.atlas_options = cfg.atlas_options_win # '-run'
else:
config.atlas_cmd = cfg.atlas_cmd_linux #'/home/share/sedatools/bin/deckbuild'
config.atlas_options = cfg.atlas_options_linux # '-run -ascii'
# config.atlas_options = '-V 5.30.0.R -run -ascii'
'''
[ドキュメント]
def get_cmd(app, xk_all, fit):
"""
外部スクリプト実行のためのコマンドライン文字列を生成します。
詳細説明:
`app.config_cmd`に設定された外部スクリプト(`config.script`)のパスとモード、
そしてフィッティングに関連するファイルパスとフィッティングパラメータ`xk_all`を
結合して実行可能なコマンドライン文字列を構築します。
:param app: アプリケーションのグローバル設定を保持するオブジェクト。
:type app: object
:param xk_all: 全てのフィッティングパラメータのリスト。
:type xk_all: list[float]
:param fit: フィッティングに関する設定やデータを含むオブジェクト(例: tkFit_mxy)。
:type fit: object
:returns: 実行するコマンドライン文字列。
:rtype: str
"""
config = app.config_cmd
config.mode = 'fit'
config.infile = fit.infile
config.datafile = fit.datafile
config.fplot = 0
head = f"python {config.script} {config.mode} {config.infile} {config.datafile}"
s = ''
for x in xk_all:
s += f" {x}"
return head + s
[ドキュメント]
def initialize(app):
"""
アプリケーションの基本設定を初期化します。
詳細説明:
`tkParams`オブジェクトを`app.cfg`に設定し、デフォルトのコンフィグレーションファイル
(`arg_config_file`)やフィッティング設定ファイル (`fit_config_file`) を読み込みます。
グラフのデフォルトサイズなどもここで設定されます。
:param app: アプリケーションのグローバル設定を保持するオブジェクト。
:type app: object
:returns: 初期化された設定オブジェクト`app.cfg`。
:rtype: tklib.tkparams.tkParams
"""
app.cfg = tkParams()
app.cfg.figsize = [8, 6]
app.arg_config_file, app.fit_config_file = opt.get_default_config_paths(app, app.cfg)
app.fit_config_file = None # このモジュールではfit_config_fileは使わない?
if app.arg_config_file: opt.read_default_config_file(app, app.arg_config_file)
if app.fit_config_file: opt.read_default_fit_file(app, app.fit_config_file)
return app.cfg
[ドキュメント]
def save_parameter_files(config_path, fitparam_path, fit, cfg, values = None, print_level = 1):
"""
設定ファイルとフィッティングパラメータファイルを保存します。
詳細説明:
汎用設定 (`cfg`) とフィッティング特有のパラメータ (`fit`) を、
指定されたパスにINI形式で保存します。
設定は複数のセクション("Preferences", "Files", "Data", "Flags", "Condition", "Scan")に
分けて保存され、特定のキーは除外またはグループ化されます。
フィッティングパラメータは"Parameters"セクションに保存されます。
:param config_path: `cfg`オブジェクトのパラメータを保存するファイルパス。
:type config_path: str
:param fitparam_path: `fit`オブジェクトのパラメータを保存するファイルパス。
:type fitparam_path: str
:param fit: フィッティングパラメータを保持する`tkFit_mxy`または類似のオブジェクト。
:type fit: object
:param cfg: 全体設定を保持する`tkParams`オブジェクト。
:type cfg: tklib.tkparams.tkParams
:param values: (Optional) フィッティングパラメータとして保存する値のリスト。Noneの場合は`fit`オブジェクトから取得されます。
:type values: list[float] or None
:param print_level: (Optional) ログ出力レベル。0で出力なし、1で主要な出力。デフォルトは1。
:type print_level: int
:returns: なし
:rtype: None
"""
flag_keys = ["fhistory", "ffitfiles", "fdisconnect_backward_data"]
files_keys = ["templatepath", "datafile", "infile", "calfile", "outfile", "datafile", "historyfile", "fitfile"]
condiction_keys = ["method", "jac", "nmaxiter", "nmaxcall", "tol", "xatol", "y_scale"]
data_keys = ["sample", "Tmin", "Tmax", "Nmin", "Nmax"]
scan_keys = ["target_var", "x0", "x1", "nx"]
if fit.varname is None: fit.varname = []
exclude_keys = condiction_keys + flag_keys + fit.varname + files_keys + data_keys + scan_keys \
+ ["infile", "logfile", "outfile", "parameterfile", "stopfile",
"fplot", "mode", "daemon", "nohup"]
print(f"Save configuration parameters to [{config_path}]")
cfg.save_parameters(config_path, section = "Preferences", exclude_keys = exclude_keys, IsPrint = print_level)
cfg.save_parameters(config_path, section = "Files", keys = files_keys, IsPrint = print_level)
cfg.save_parameters(config_path, section = "Data", keys = data_keys, IsPrint = print_level)
cfg.save_parameters(config_path, section = "Flags", keys = flag_keys, IsPrint = print_level)
cfg.save_parameters(config_path, section = "Condition", keys = condiction_keys, IsPrint = print_level)
cfg.save_parameters(config_path, section = "Scan", keys = scan_keys, IsPrint = print_level)
if print_level:
print(f"Save fitting parameters to [{fitparam_path}] (save_parameters)")
fit.save_parameters(fitparam_path, section = "Parameters", keys = fit.varname, vars = fit, values = values, print_level = 0)
# fit.print_variables(heading = "fitting parameters (save_parameters):")
[ドキュメント]
def read_parameters(path, cfg):
"""
指定されたパスから、フィッティングパラメータ以外の設定を読み込みます。
詳細説明:
`cfg`オブジェクトに、特定のセクション (`Preferences`, `Flags`, `Files`, `Scan`, `Condition`) の
パラメータをINIファイルから読み込みます。
"Parameters"セクションは読み込まず、一部のキーは無視されます。
:param path: パラメータを読み込むINIファイルのパス。
:type path: str
:param cfg: 読み込んだ設定を格納する`tkParams`オブジェクト。
:type cfg: tklib.tkparams.tkParams
:returns: なし
:rtype: None
"""
#Parametersセクション以外のみ読み込む
sectios = ["Preferences", "Flags", "Files", "Scan", "Condition"]
ignore_keys = ["logfile", "outfile", "parameterfile", "parameterbkfile",
"file1", "file2", "file3", "file4", "file5",
"fplot", "mode", "daemon", "nohup"]
print(f"Read parameters from [{path}]")
for section in sectios:
cfg.read_parameters(cfg.parameterfile, section = section, ignore_keys = ignore_keys)
[ドキュメント]
def init_fit(app, cfg, print_level = 1):
"""
フィッティングプロセスで使用する`tkFit_mxy`オブジェクトを初期化および設定します。
詳細説明:
アプリケーション設定 (`app`), 全体設定 (`cfg`) を基に、フィッティングメソッド、
許容誤差、反復回数などの条件を設定し、フィッティングパラメータをファイルから読み込みます。
また、`tkFit_mxy`オブジェクトが呼び出す各種コールバック関数
(`cal_ylist`, `minimize_func`, `callback`, `cal_penalty`, `cal_fmin`, `save_parameter_files`)
を定義し、グラフ関連の変数も設定します。
:param app: アプリケーションのグローバル設定を保持するオブジェクト。
:type app: object
:param cfg: 全体設定を保持する`tkParams`オブジェクト。
:type cfg: tklib.tkparams.tkParams
:param print_level: (Optional) ログ出力レベル。デフォルトは1。
:type print_level: int
:returns: 初期化および設定されたフィッティングオブジェクト。
:rtype: tklib.tksci.tkFit_mxy_flex.tkFit_mxy
"""
#パラメータファイルの読み込み。Parametersセクション以外のみ
print("In tkminimize_func.read_parameters():")
read_parameters(cfg.parameterfile, cfg)
app.force_given_args(cfg)
print("mode : {}".format(cfg.mode))
print("fplot : {}".format(cfg.fplot))
print("fhistory : {}".format(cfg.fhistory))
print("ffitfiles : {}".format(cfg.ffitfiles))
print("stop path : {}".format(cfg.stopfile))
print("infile : {}".format(cfg.infile))
print("outfile : {}".format(cfg.outfile))
fit = tkFit_mxy(app = app, method = cfg.method, jac = cfg.jac, tol = cfg.tol, xatol = cfg.get("xatol", 1.0e-4),
nmaxiter = cfg.nmaxiter, nmaxcall = cfg.nmaxcall,
fplot = cfg.fplot, fdisconnect_backward_data = cfg.get("fdisconnect_backward_data", False),
print_interval = cfg.print_interval, plot_interval = cfg.plot_interval)
app.fit = fit
fit.fitfile_path = app.replace_path(cfg.infile, template = ["{dirname}", getattr(cfg, "fitfile_template", "{filebody}_parameters.csv")])
print()
print("config parameter file : {}".format(cfg.parameterfile))
# print("parameter backup file: {}".format(cfg.parameterbkfile))
print("fitting parameter file: {}".format(fit.fitfile_path))
print("history file : {}".format(cfg.historyfile))
print()
print(f"Fitting configuration")
print(f" method : {cfg.method}")
print(f" jac : {cfg.jac}")
print(f" tol : {cfg.tol}")
print(f" nmaxiter: {cfg.nmaxiter}")
print(f" nmaxcall: {cfg.nmaxcall}")
print(f" y_scale : {cfg.y_scale}")
fit.configure(print_level = 0, cfg = cfg)
fit.copy_attributes(cfg, ["T", "infile", "outfile", "historyfile", "fitfile",
"templatepath", "datafile", "atlasfile", "logfile", "Cfile",
"defectaccfile", "defectdonfile", "atlaslogfile", "calfile"])
fit.copy_attributes(cfg, ["fmax_record", "y_scale"])
fit.copy_attributes(cfg, ["initialize_method", "surrogate_model", "surrogate_method",
"nparents", "ga_nmaxiter", "nmaxdata", "xatol",
"mutation_rate", "n_restarts_optimizer", "alpha"])
# appに定義したフィッティングパラメータ設定をfitにコピー
fit.copy_attributes(app, ["varname", "unit", "pk_scale", "optid", "linid", "dx", "kmin", "kmax", "kpenalty"])
# フィッティングパラメーターの初期値をfit変数から設定
# x0 = fit.build_parameter_list(fit.varname, source_obj = cfg)
if hasattr(app, "x0"): fit.pk = app.x0.copy()
# fit.print_variables(heading = f"Fitting parameters red from [{fit.fitfile_path}]:")
# exit()
# Fittingパラメータファイルからフィッティング変数の初期値を設定
fit.read_parameters(fit.fitfile_path, section = "Parameters", keys = fit.varname)
nvars = len(fit.pk)
fit.print_variables(heading = f"Fitting parameters red from [{fit.fitfile_path}]:")
# exit()
#起動時引数で与えられたパラメータを再設定
app.force_given_args(cfg)
fit.initial_simplex = None
if 'fit' in cfg.mode and (cfg.method == 'nelder-mead' or cfg.method == 'simplex'):
if fit.dx:
fit.initial_simplex = fit.build_initial_simplex()
for i, splx in enumerate(fit.initial_simplex):
print(f" {i}: ", end = '')
for v in splx:
print(f" {v:12.4g}", end = '')
print()
# fitから呼び出される関数の定義
if cfg.jac == 'func':
fit.jac = lambda xk: diff1(xk, fit) # diff1関数は現在のコードには存在しないが、元のロジックに従う
else:
fit.jac = cfg.jac
fit.configure(cal_ylist = lambda xk_all, x_list = fit.x_list, run = cfg.run, print_level = 1: \
cal_ylist(app, xk_all, x_list = x_list, fit = fit, run = run, print_level = print_level),
minimize_func = lambda pk, run = cfg.run, print_level = print_level: \
fit._minimize_func(pk, x_list = fit.x_list, y_list = fit.y_list, w_list = fit.w_list,
run = cfg.run, print_level = print_level),
callback = lambda pk, run = cfg.run, savefig_path = 'last_fit.png', use_so = False, print_level = 1: \
fit._callback(pk, run = cfg.run, savefig_path = savefig_path, use_so = use_so, print_level = print_level),
cal_penalty = lambda xk_all, run = cfg.run, print_level = 1: \
fit._cal_penalty(xk_all, print_level),
cal_fmin = lambda xk_all, x_list, y_list, w_list, run = cfg.run, print_level = 1: \
fit._cal_fmin(xk_all, x_list, y_list, w_list, run, print_level = print_level),
save_parameter_files = lambda config_path, fitparam_path, cfg, values = None, print_level = 1: \
save_parameter_files(config_path, fitparam_path, fit, cfg, values = values, print_level = print_level),
)
# fitのグラフ関連変数の定義
fit.configure(fplot = fit.fplot, plt = plt, iter = 0, xiter = [], yfmin = [], ycal_list = None, yfin_list = None)
return fit
[ドキュメント]
def cal_ylist(app, xk_all, x_list, fit = None, run = True, print_level = 1):
"""
フィッティングパラメータと入力XデータからモデルのYデータを計算します。
詳細説明:
`peakfit`モジュール (`omodel`) の`cal_ylist`関数を呼び出し、
与えられたフィッティングパラメータ`xk_all`とXデータ`x_list`を用いて、
モデルが予測するYデータを計算します。この関数は、フィッティングプロセス中に
モデルの出力値を生成するために使用されます。
:param app: アプリケーションのグローバル設定を保持するオブジェクト。
:type app: object
:param xk_all: 全てのフィッティングパラメータのリスト。
:type xk_all: list[float]
:param x_list: Xデータのリスト(モデルの入力)。
:type x_list: list[numpy.ndarray]
:param fit: (Optional) フィッティングに関する設定やデータを含むオブジェクト。デフォルトはNone。
:type fit: object or None
:param run: (Optional) 計算を実行するかどうかのフラグ。Trueの場合、計算を実行します。デフォルトはTrue。
:type run: bool
:param print_level: (Optional) ログ出力レベル。デフォルトは1。
:type print_level: int
:returns: 計算されたYデータのリスト。
:rtype: list[numpy.ndarray]
"""
ylist = omodel.cal_ylist(app, xk_all, x_list, fit = fit, run = run, print_level = print_level)
return ylist