pyfemtet 0.4.13__py3-none-any.whl → 0.4.14__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyfemtet might be problematic. Click here for more details.
- pyfemtet/__init__.py +1 -1
- pyfemtet/dispatch_extensions.py +4 -0
- pyfemtet/message/1. make_pot.bat +12 -0
- pyfemtet/message/2. make_mo.bat +6 -0
- pyfemtet/message/__init__.py +5 -0
- pyfemtet/message/babel.cfg +2 -0
- pyfemtet/message/locales/ja/LC_MESSAGES/messages.po +449 -0
- pyfemtet/message/locales/messages.pot +439 -0
- pyfemtet/message/messages.py +174 -0
- pyfemtet/opt/_femopt.py +9 -9
- pyfemtet/opt/_femopt_core.py +16 -14
- pyfemtet/opt/femprj_sample/ParametricIF_test_result.reccsv +13 -13
- pyfemtet/opt/femprj_sample/cad_ex01_NX_test_result.reccsv +13 -13
- pyfemtet/opt/femprj_sample/cad_ex01_SW_test_result.reccsv +13 -13
- pyfemtet/opt/femprj_sample/gal_ex58_parametric_test_result.reccsv +13 -13
- pyfemtet/opt/femprj_sample/gau_ex08_parametric_test_result.reccsv +23 -23
- pyfemtet/opt/femprj_sample/her_ex40_parametric_test_result.reccsv +18 -18
- pyfemtet/opt/femprj_sample/paswat_ex1_parametric_test_result.reccsv +18 -18
- pyfemtet/opt/femprj_sample/tutorial.femprj +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14.pdt +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14_trial1.jpg +0 -0
- pyfemtet/opt/{visualization/result_viewer/tutorial → femprj_sample}/wat_ex14_parametric.Results/Ex14_trial1.pdt +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14_trial10.jpg +0 -0
- pyfemtet/opt/{visualization/result_viewer/tutorial → femprj_sample}/wat_ex14_parametric.Results/Ex14_trial10.pdt +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14_trial11.jpg +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14_trial11.pdt +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14_trial12.jpg +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14_trial12.pdt +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14_trial13.jpg +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14_trial13.pdt +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14_trial14.jpg +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14_trial14.pdt +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14_trial15.jpg +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14_trial15.pdt +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14_trial2.jpg +0 -0
- pyfemtet/opt/{visualization/result_viewer/tutorial → femprj_sample}/wat_ex14_parametric.Results/Ex14_trial2.pdt +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14_trial3.jpg +0 -0
- pyfemtet/opt/{visualization/result_viewer/tutorial → femprj_sample}/wat_ex14_parametric.Results/Ex14_trial3.pdt +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14_trial4.jpg +0 -0
- pyfemtet/opt/{visualization/result_viewer/tutorial → femprj_sample}/wat_ex14_parametric.Results/Ex14_trial4.pdt +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14_trial5.jpg +0 -0
- pyfemtet/opt/{visualization/result_viewer/tutorial → femprj_sample}/wat_ex14_parametric.Results/Ex14_trial5.pdt +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14_trial6.jpg +0 -0
- pyfemtet/opt/{visualization/result_viewer/tutorial → femprj_sample}/wat_ex14_parametric.Results/Ex14_trial6.pdt +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14_trial7.jpg +0 -0
- pyfemtet/opt/{visualization/result_viewer/tutorial → femprj_sample}/wat_ex14_parametric.Results/Ex14_trial7.pdt +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14_trial8.jpg +0 -0
- pyfemtet/opt/{visualization/result_viewer/tutorial → femprj_sample}/wat_ex14_parametric.Results/Ex14_trial8.pdt +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.Results/Ex14_trial9.jpg +0 -0
- pyfemtet/opt/{visualization/result_viewer/tutorial → femprj_sample}/wat_ex14_parametric.Results/Ex14_trial9.pdt +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric_test_result.reccsv +18 -18
- pyfemtet/opt/interface/_femtet.py +42 -46
- pyfemtet/opt/interface/_femtet_with_nx/_interface.py +4 -4
- pyfemtet/opt/interface/_femtet_with_nx/update_model.py +6 -6
- pyfemtet/opt/interface/_femtet_with_sldworks.py +5 -4
- pyfemtet/opt/opt/__init__.py +2 -0
- pyfemtet/opt/opt/_base.py +41 -20
- pyfemtet/opt/opt/_optuna.py +8 -13
- pyfemtet/opt/opt/_scipy.py +4 -8
- pyfemtet/opt/opt/_scipy_scalar.py +1 -5
- pyfemtet/opt/prediction/__init__.py +0 -0
- pyfemtet/opt/prediction/base.py +52 -0
- pyfemtet/opt/prediction/single_task_gp.py +82 -0
- pyfemtet/opt/visualization/complex_components/control_femtet.py +9 -11
- pyfemtet/opt/visualization/complex_components/main_figure_creator.py +24 -11
- pyfemtet/opt/visualization/complex_components/main_graph.py +3 -4
- pyfemtet/opt/visualization/complex_components/pm_graph.py +715 -0
- pyfemtet/opt/visualization/complex_components/pm_graph_creator.py +168 -0
- pyfemtet/opt/visualization/process_monitor/application.py +16 -12
- pyfemtet/opt/visualization/process_monitor/pages.py +22 -7
- pyfemtet/opt/visualization/result_viewer/application.py +8 -3
- pyfemtet/opt/visualization/result_viewer/pages.py +59 -47
- {pyfemtet-0.4.13.dist-info → pyfemtet-0.4.14.dist-info}/METADATA +2 -1
- {pyfemtet-0.4.13.dist-info → pyfemtet-0.4.14.dist-info}/RECORD +77 -70
- pyfemtet/opt/visualization/result_viewer/tutorial/tutorial.csv +0 -18
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14.jpg +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14.log +0 -81
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14.pdt +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_heatflow.csv +0 -28
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_heatflow_el.csv +0 -22
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_trial1.jpg +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_trial10.jpg +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_trial11.jpg +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_trial11.pdt +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_trial12.jpg +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_trial12.pdt +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_trial13.jpg +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_trial13.pdt +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_trial14.jpg +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_trial14.pdt +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_trial15.jpg +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_trial15.pdt +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_trial2.jpg +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_trial3.jpg +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_trial4.jpg +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_trial5.jpg +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_trial6.jpg +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_trial7.jpg +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_trial8.jpg +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.Results/Ex14_trial9.jpg +0 -0
- pyfemtet/opt/visualization/result_viewer/tutorial/wat_ex14_parametric.femprj +0 -0
- {pyfemtet-0.4.13.dist-info → pyfemtet-0.4.14.dist-info}/LICENSE +0 -0
- {pyfemtet-0.4.13.dist-info → pyfemtet-0.4.14.dist-info}/WHEEL +0 -0
- {pyfemtet-0.4.13.dist-info → pyfemtet-0.4.14.dist-info}/entry_points.txt +0 -0
pyfemtet/opt/opt/_scipy.py
CHANGED
|
@@ -15,6 +15,7 @@ from scipy.optimize import minimize, OptimizeResult
|
|
|
15
15
|
from pyfemtet.opt._femopt_core import OptimizationStatus, generate_lhs
|
|
16
16
|
from pyfemtet.opt.opt import AbstractOptimizer, logger, OptimizationMethodChecker
|
|
17
17
|
from pyfemtet.core import MeshError, ModelError, SolveError
|
|
18
|
+
from pyfemtet.message import Msg
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
class StopIteration2(Exception):
|
|
@@ -85,11 +86,8 @@ class ScipyOptimizer(AbstractOptimizer):
|
|
|
85
86
|
try:
|
|
86
87
|
_, obj_values, cns_values = self.f(x)
|
|
87
88
|
except (ModelError, MeshError, SolveError) as e:
|
|
88
|
-
|
|
89
|
-
logger.
|
|
90
|
-
print(self.get_parameter('dict'))
|
|
91
|
-
|
|
92
|
-
# 現状、エラーが起きたらスキップできない
|
|
89
|
+
# 現在の技術的にエラーが起きたらスキップできない
|
|
90
|
+
logger.error(Msg.ERR_FEM_FAILED_AND_CANNOT_CONTINUE)
|
|
93
91
|
raise StopIteration2
|
|
94
92
|
|
|
95
93
|
# constraints
|
|
@@ -134,9 +132,7 @@ class ScipyOptimizer(AbstractOptimizer):
|
|
|
134
132
|
)
|
|
135
133
|
except StopIteration2:
|
|
136
134
|
res = None
|
|
137
|
-
logger.warn(
|
|
138
|
-
'Note that you cannot acquire the OptimizationResult '
|
|
139
|
-
'in case of `trust-constr`, `TNC`, `SLSQP` or `COBYLA`.')
|
|
135
|
+
logger.warn(Msg.WARN_INTERRUPTED_IN_SCIPY)
|
|
140
136
|
|
|
141
137
|
if res is None:
|
|
142
138
|
self.res = self.stop_iteration_callback.res
|
|
@@ -21,7 +21,7 @@ class ScipyScalarMethodChecker(OptimizationMethodChecker):
|
|
|
21
21
|
def check_incomplete_bounds(self, raise_error=True): return True
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
class
|
|
24
|
+
class ScipyScalarOptimizer(AbstractOptimizer):
|
|
25
25
|
|
|
26
26
|
def __init__(
|
|
27
27
|
self,
|
|
@@ -51,10 +51,6 @@ class ScipyOptimizer(AbstractOptimizer):
|
|
|
51
51
|
try:
|
|
52
52
|
_, obj_values, cns_values = self.f(x)
|
|
53
53
|
except (ModelError, MeshError, SolveError) as e:
|
|
54
|
-
logger.info(e)
|
|
55
|
-
logger.info('以下の変数で FEM 解析に失敗しました。')
|
|
56
|
-
print(self.get_parameter('dict'))
|
|
57
|
-
|
|
58
54
|
# 現状、エラーが起きたらスキップできない
|
|
59
55
|
raise StopIteration
|
|
60
56
|
|
|
File without changes
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pandas as pd
|
|
5
|
+
|
|
6
|
+
from pyfemtet.opt._femopt_core import History
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class PredictionModelBase(ABC):
|
|
10
|
+
|
|
11
|
+
@abstractmethod
|
|
12
|
+
def fit(self, x: np.ndarray, y: np.ndarray):
|
|
13
|
+
"""
|
|
14
|
+
Parameters:
|
|
15
|
+
x (np.ndarray): Input. (Point number) rows and (variable number) columns.
|
|
16
|
+
y (np.ndarray): Output. (Point number) rows and (objective number) columns.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
@abstractmethod
|
|
20
|
+
def predict(self, x: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
|
|
21
|
+
"""
|
|
22
|
+
Parameters:
|
|
23
|
+
x (np.ndarray): Input. (Point number) rows and (variable number) columns.
|
|
24
|
+
Returns:
|
|
25
|
+
np.ndarray: (Point number) rows and (objective number) columns. Index 0 is mean and index 1 is std.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class PyFemtetPredictionModel:
|
|
30
|
+
|
|
31
|
+
def __init__(self, history: History, df: pd.DataFrame, MetaModel: type):
|
|
32
|
+
assert issubclass(MetaModel, PredictionModelBase)
|
|
33
|
+
self.meta_model: PredictionModelBase = MetaModel()
|
|
34
|
+
self.obj_names = history.obj_names
|
|
35
|
+
self.prm_names = history.prm_names
|
|
36
|
+
self.df = df
|
|
37
|
+
self.x: np.ndarray = df[self.prm_names].values
|
|
38
|
+
self.y: np.ndarray = df[self.obj_names].values
|
|
39
|
+
|
|
40
|
+
def get_prm_index(self, prm_name):
|
|
41
|
+
return self.prm_names.index(prm_name) if prm_name in self.prm_names else None
|
|
42
|
+
|
|
43
|
+
def get_obj_index(self, obj_name):
|
|
44
|
+
return self.obj_names.index(obj_name) if obj_name in self.obj_names else None
|
|
45
|
+
|
|
46
|
+
def fit(self) -> None:
|
|
47
|
+
self.meta_model.fit(self.x, self.y)
|
|
48
|
+
|
|
49
|
+
def predict(self, x: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
|
|
50
|
+
assert len(x.shape) == 2
|
|
51
|
+
assert x.shape[1] == len(self.prm_names)
|
|
52
|
+
return self.meta_model.predict(x)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import torch
|
|
3
|
+
import gpytorch
|
|
4
|
+
|
|
5
|
+
from botorch.models import SingleTaskGP
|
|
6
|
+
from botorch.fit import fit_gpytorch_mll
|
|
7
|
+
from gpytorch.mlls import ExactMarginalLogLikelihood
|
|
8
|
+
|
|
9
|
+
from pyfemtet.opt.prediction.base import PredictionModelBase
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class MyStandardScaler:
|
|
13
|
+
|
|
14
|
+
# noinspection PyAttributeOutsideInit
|
|
15
|
+
def fit_transform(self, x: torch.Tensor) -> torch.Tensor:
|
|
16
|
+
self.m = x.numpy().mean(axis=0)
|
|
17
|
+
self.s = x.numpy().std(axis=0, ddof=1)
|
|
18
|
+
return self.transform(x)
|
|
19
|
+
|
|
20
|
+
def transform(self, x: torch.Tensor) -> torch.Tensor:
|
|
21
|
+
return torch.tensor((x.numpy() - self.m) / self.s).double()
|
|
22
|
+
|
|
23
|
+
def inverse_transform_mean(self, x: torch.Tensor) -> torch.Tensor:
|
|
24
|
+
return torch.tensor(x.numpy() * self.s + self.m).double()
|
|
25
|
+
|
|
26
|
+
def inverse_transform_var(self, x: torch.Tensor) -> torch.Tensor:
|
|
27
|
+
return torch.tensor(x.numpy() * self.s**2).double()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class MyMinMaxScaler:
|
|
31
|
+
|
|
32
|
+
# noinspection PyAttributeOutsideInit
|
|
33
|
+
def fit_transform(self, x: torch.Tensor) -> torch.Tensor:
|
|
34
|
+
self.max = x.numpy().max(axis=0)
|
|
35
|
+
self.min = x.numpy().min(axis=0)
|
|
36
|
+
return self.transform(x)
|
|
37
|
+
|
|
38
|
+
def transform(self, x: torch.Tensor) -> torch.Tensor:
|
|
39
|
+
return torch.tensor((x.numpy() - self.min) / (self.max - self.min)).double()
|
|
40
|
+
|
|
41
|
+
def inverse_transform_mean(self, x: torch.Tensor) -> torch.Tensor:
|
|
42
|
+
return torch.tensor(x.numpy() * (self.max - self.min) + self.min).double()
|
|
43
|
+
|
|
44
|
+
def inverse_transform_var(self, x: torch.Tensor) -> torch.Tensor:
|
|
45
|
+
return torch.tensor(x.numpy() * (self.max - self.min)**2).double()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class SingleTaskGPModel(PredictionModelBase):
|
|
49
|
+
|
|
50
|
+
# noinspection PyAttributeOutsideInit
|
|
51
|
+
def fit(self, x: np.ndarray, y: np.ndarray):
|
|
52
|
+
train_x = torch.tensor(x).double()
|
|
53
|
+
train_y = torch.tensor(y).double()
|
|
54
|
+
|
|
55
|
+
# Normalize the input data to the unit cube
|
|
56
|
+
self.scaler_x = MyMinMaxScaler()
|
|
57
|
+
train_x = self.scaler_x.fit_transform(train_x)
|
|
58
|
+
|
|
59
|
+
# Standardize the output data
|
|
60
|
+
self.scaler_y = MyStandardScaler()
|
|
61
|
+
train_y = self.scaler_y.fit_transform(train_y)
|
|
62
|
+
|
|
63
|
+
# Fit a Gaussian Process model using the extracted data
|
|
64
|
+
self.gp = SingleTaskGP(train_x, train_y)
|
|
65
|
+
mll = ExactMarginalLogLikelihood(self.gp.likelihood, self.gp)
|
|
66
|
+
fit_gpytorch_mll(mll)
|
|
67
|
+
|
|
68
|
+
def predict(self, x: np.ndarray) -> list[np.ndarray, np.ndarray]:
|
|
69
|
+
x = torch.tensor(x).double()
|
|
70
|
+
self.gp.eval()
|
|
71
|
+
with torch.no_grad(), gpytorch.settings.fast_pred_var():
|
|
72
|
+
# normalized
|
|
73
|
+
scaled_x = self.scaler_x.transform(x)
|
|
74
|
+
# predict
|
|
75
|
+
pred = self.gp(scaled_x)
|
|
76
|
+
scaled_mean = torch.permute(pred.mean, (1, 0))
|
|
77
|
+
scaled_var = torch.permute(pred.variance, (1, 0))
|
|
78
|
+
# unscaling
|
|
79
|
+
mean = self.scaler_y.inverse_transform_mean(scaled_mean).numpy()
|
|
80
|
+
var = self.scaler_y.inverse_transform_var(scaled_var).numpy()
|
|
81
|
+
std = np.sqrt(var)
|
|
82
|
+
return mean, std
|
|
@@ -18,6 +18,7 @@ from pythoncom import com_error
|
|
|
18
18
|
|
|
19
19
|
from pyfemtet.opt.visualization.base import PyFemtetApplicationBase, AbstractPage, logger
|
|
20
20
|
from pyfemtet.opt.interface._femtet import FemtetInterface
|
|
21
|
+
from pyfemtet.message import Msg
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
class FemtetState(Enum):
|
|
@@ -44,7 +45,7 @@ class FemtetControl(AbstractPage):
|
|
|
44
45
|
# button
|
|
45
46
|
# noinspection PyAttributeOutsideInit
|
|
46
47
|
self.connect_femtet_button = dbc.Button(
|
|
47
|
-
children=
|
|
48
|
+
children=Msg.LABEL_CONNECT_FEMTET_BUTTON,
|
|
48
49
|
id='connect-femtet-button',
|
|
49
50
|
outline=True,
|
|
50
51
|
color='primary',
|
|
@@ -101,7 +102,7 @@ class FemtetControl(AbstractPage):
|
|
|
101
102
|
# model_name is not included in femprj
|
|
102
103
|
kwargs.update(dict(model_name=None))
|
|
103
104
|
self.fem = FemtetInterface(**kwargs)
|
|
104
|
-
warning_msg =
|
|
105
|
+
warning_msg = Msg.WARN_CSV_MODEL_NAME_IS_INVALID
|
|
105
106
|
|
|
106
107
|
# if 'new' femtet, Interface try to terminate Femtet when the self.fem is reconstructed.
|
|
107
108
|
self.fem.quit_when_destruct = False
|
|
@@ -136,39 +137,36 @@ class FemtetControl(AbstractPage):
|
|
|
136
137
|
|
|
137
138
|
# check holding history
|
|
138
139
|
if self.application.history is None:
|
|
139
|
-
return kwargs,
|
|
140
|
+
return kwargs, Msg.ERR_HISTORY_CSV_NOT_READ
|
|
140
141
|
|
|
141
142
|
# get metadata
|
|
142
143
|
additional_metadata = self.application.history.metadata[0]
|
|
143
144
|
|
|
144
145
|
# check metadata exists
|
|
145
146
|
if additional_metadata == '':
|
|
146
|
-
return kwargs,
|
|
147
|
+
return kwargs, Msg.WARN_INVALID_METADATA
|
|
147
148
|
|
|
148
149
|
# check the metadata is valid json
|
|
149
150
|
try:
|
|
150
151
|
d = json.loads(additional_metadata)
|
|
151
152
|
femprj_path = os.path.abspath(d['femprj_path'])
|
|
152
153
|
except (TypeError, json.decoder.JSONDecodeError, KeyError):
|
|
153
|
-
return kwargs,
|
|
154
|
-
'Valid format is like: '
|
|
155
|
-
'"{""femprj_path"": ""c:\\path\\to\\sample.femprj"", ""model_name"": ""<model_name>""}". '
|
|
156
|
-
'Open your project manually.')
|
|
154
|
+
return kwargs, Msg.WARN_INVALID_METADATA
|
|
157
155
|
|
|
158
156
|
# check containing femprj
|
|
159
157
|
if femprj_path is None:
|
|
160
|
-
return kwargs,
|
|
158
|
+
return kwargs, Msg.WARN_INVALID_METADATA
|
|
161
159
|
|
|
162
160
|
# check femprj exists
|
|
163
161
|
if not os.path.exists(femprj_path):
|
|
164
|
-
return kwargs,
|
|
162
|
+
return kwargs, Msg.WARN_FEMPRJ_IN_CSV_NOT_FOUND
|
|
165
163
|
|
|
166
164
|
# at this point, femprj is valid at least.
|
|
167
165
|
kwargs.update({'femprj_path': femprj_path})
|
|
168
166
|
|
|
169
167
|
# check model name
|
|
170
168
|
model_name = d['model_name'] if 'model_name' in d.keys() else None
|
|
171
|
-
msg = '' if model_name is not None else
|
|
169
|
+
msg = '' if model_name is not None else Msg.WARN_MODEL_IN_CSV_NOT_FOUND_IN_FEMPRJ
|
|
172
170
|
kwargs.update({'model_name': model_name})
|
|
173
171
|
return kwargs, msg
|
|
174
172
|
|
|
@@ -2,6 +2,7 @@ import plotly.graph_objs as go
|
|
|
2
2
|
import plotly.express as px
|
|
3
3
|
|
|
4
4
|
from pyfemtet.opt._femopt_core import History
|
|
5
|
+
from pyfemtet.message import Msg
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
class _ColorSet:
|
|
@@ -17,11 +18,17 @@ class _LanguageSet:
|
|
|
17
18
|
feasible = {'label': 'feasible', True: True, False: False}
|
|
18
19
|
non_domi = {'label': 'non_domi', True: True, False: False}
|
|
19
20
|
|
|
20
|
-
def __init__(self
|
|
21
|
-
self.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
def __init__(self):
|
|
22
|
+
self.feasible = {
|
|
23
|
+
'label': Msg.LEGEND_LABEL_CONSTRAINT,
|
|
24
|
+
True: Msg.LEGEND_LABEL_FEASIBLE,
|
|
25
|
+
False: Msg.LEGEND_LABEL_INFEASIBLE,
|
|
26
|
+
}
|
|
27
|
+
self.non_domi = {
|
|
28
|
+
'label': Msg.LEGEND_LABEL_OPTIMAL,
|
|
29
|
+
True: Msg.LEGEND_LABEL_NON_DOMI,
|
|
30
|
+
False: Msg.LEGEND_LABEL_DOMI,
|
|
31
|
+
}
|
|
25
32
|
|
|
26
33
|
def localize(self, df):
|
|
27
34
|
# 元のオブジェクトを変更しないようにコピー
|
|
@@ -34,7 +41,7 @@ class _LanguageSet:
|
|
|
34
41
|
return cdf
|
|
35
42
|
|
|
36
43
|
|
|
37
|
-
_ls = _LanguageSet(
|
|
44
|
+
_ls = _LanguageSet()
|
|
38
45
|
_cs = _ColorSet()
|
|
39
46
|
_ss = _SymbolSet()
|
|
40
47
|
|
|
@@ -53,7 +60,10 @@ def get_hypervolume_plot(_: History, df):
|
|
|
53
60
|
|
|
54
61
|
fig.update_layout(
|
|
55
62
|
dict(
|
|
56
|
-
title_text=
|
|
63
|
+
title_text=Msg.GRAPH_TITLE_HYPERVOLUME,
|
|
64
|
+
transition_duration=1000,
|
|
65
|
+
xaxis_title=Msg.GRAPH_AXIS_LABEL_TRIAL,
|
|
66
|
+
yaxis_title='hypervolume',
|
|
57
67
|
)
|
|
58
68
|
)
|
|
59
69
|
|
|
@@ -76,7 +86,10 @@ def get_default_figure(history, df):
|
|
|
76
86
|
fig = _get_multi_objective_pairplot(history, df)
|
|
77
87
|
|
|
78
88
|
fig.update_traces(hoverinfo="none", hovertemplate=None)
|
|
79
|
-
fig.update_layout(
|
|
89
|
+
fig.update_layout(
|
|
90
|
+
clickmode='event+select',
|
|
91
|
+
transition_duration=1000,
|
|
92
|
+
)
|
|
80
93
|
|
|
81
94
|
return fig
|
|
82
95
|
|
|
@@ -120,8 +133,8 @@ def _get_single_objective_plot(history, df):
|
|
|
120
133
|
|
|
121
134
|
fig.update_layout(
|
|
122
135
|
dict(
|
|
123
|
-
title_text=
|
|
124
|
-
xaxis_title=
|
|
136
|
+
title_text=Msg.GRAPH_TITLE_SINGLE_OBJECTIVE,
|
|
137
|
+
xaxis_title=Msg.GRAPH_AXIS_LABEL_TRIAL,
|
|
125
138
|
yaxis_title=obj_name,
|
|
126
139
|
)
|
|
127
140
|
)
|
|
@@ -182,7 +195,7 @@ def _get_multi_objective_pairplot(history, df):
|
|
|
182
195
|
|
|
183
196
|
fig.update_layout(
|
|
184
197
|
dict(
|
|
185
|
-
title_text=
|
|
198
|
+
title_text=Msg.GRAPH_TITLE_MULTI_OBJECTIVE,
|
|
186
199
|
)
|
|
187
200
|
)
|
|
188
201
|
|
|
@@ -22,6 +22,7 @@ import numpy as np
|
|
|
22
22
|
|
|
23
23
|
from pyfemtet.opt.visualization.complex_components import main_figure_creator
|
|
24
24
|
from pyfemtet.opt.visualization.base import PyFemtetApplicationBase, AbstractPage, logger
|
|
25
|
+
from pyfemtet.message import Msg
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
FLEXBOX_STYLE_ALLOW_VERTICAL_FILL = {
|
|
@@ -60,12 +61,12 @@ class MainGraph(AbstractPage):
|
|
|
60
61
|
self.figure_creators = [
|
|
61
62
|
dict(
|
|
62
63
|
tab_id='tab-objective-plot',
|
|
63
|
-
label=
|
|
64
|
+
label=Msg.TAB_LABEL_OBJECTIVES,
|
|
64
65
|
creator=main_figure_creator.get_default_figure,
|
|
65
66
|
),
|
|
66
67
|
dict(
|
|
67
68
|
tab_id='tab-hypervolume-plot',
|
|
68
|
-
label='
|
|
69
|
+
label='Hypervolume',
|
|
69
70
|
creator=main_figure_creator.get_hypervolume_plot,
|
|
70
71
|
),
|
|
71
72
|
]
|
|
@@ -147,8 +148,6 @@ class MainGraph(AbstractPage):
|
|
|
147
148
|
Input(self.dummy, 'children'),
|
|
148
149
|
prevent_initial_call=False,)
|
|
149
150
|
def redraw_main_graph(active_tab_id, _):
|
|
150
|
-
logger.debug('====================')
|
|
151
|
-
logger.debug(f'redraw_main_graph called by {callback_context.triggered_id}')
|
|
152
151
|
figure, length = self.get_fig_by_tab_id(active_tab_id, with_length=True)
|
|
153
152
|
return figure, length
|
|
154
153
|
|