pyfemtet 0.8.4__tar.gz → 0.8.6__tar.gz

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.

Files changed (144) hide show
  1. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/PKG-INFO +1 -1
  2. pyfemtet-0.8.6/pyfemtet/__init__.py +1 -0
  3. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/_femopt.py +37 -10
  4. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/_femopt_core.py +63 -28
  5. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/_test_utils/record_history.py +23 -16
  6. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/interface/__init__.py +4 -1
  7. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/interface/_surrogate/_base.py +11 -11
  8. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/interface/_surrogate/_singletaskgp.py +4 -3
  9. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/prediction/single_task_gp.py +6 -4
  10. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/_base.py +12 -1
  11. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/_complex_components/control_femtet.py +7 -7
  12. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/_complex_components/main_graph.py +65 -29
  13. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/_complex_components/pm_graph.py +17 -16
  14. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/_process_monitor/application.py +20 -3
  15. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/_process_monitor/pages.py +2 -2
  16. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/result_viewer/pages.py +6 -6
  17. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyproject.toml +1 -1
  18. pyfemtet-0.8.4/pyfemtet/__init__.py +0 -1
  19. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/LICENSE +0 -0
  20. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/README.md +0 -0
  21. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/_femtet_config_util/__init__.py +0 -0
  22. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/_femtet_config_util/autosave.py +0 -0
  23. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/_femtet_config_util/exit.py +0 -0
  24. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/_message/1. make_pot.bat +0 -0
  25. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/_message/2. make_mo.bat +0 -0
  26. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/_message/__init__.py +0 -0
  27. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/_message/babel.cfg +0 -0
  28. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/_message/locales/ja/LC_MESSAGES/messages.mo +0 -0
  29. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/_message/locales/ja/LC_MESSAGES/messages.po +0 -0
  30. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/_message/locales/messages.pot +0 -0
  31. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/_message/messages.py +0 -0
  32. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/_util/__init__.py +0 -0
  33. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/_util/dask_util.py +0 -0
  34. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/_util/excel_macro_util.py +0 -0
  35. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/_util/excel_parse_util.py +0 -0
  36. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/_util/sample.xlsx +0 -0
  37. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/_warning.py +0 -0
  38. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/brep/__init__.py +0 -0
  39. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/brep/_impl.py +0 -0
  40. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/core.py +0 -0
  41. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/dispatch_extensions/__init__.py +0 -0
  42. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/dispatch_extensions/_impl.py +0 -0
  43. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/logger/__init__.py +0 -0
  44. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/logger/_impl.py +0 -0
  45. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/__init__.py +0 -0
  46. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/_test_utils/__init__.py +0 -0
  47. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/_test_utils/control_femtet.py +0 -0
  48. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/_test_utils/hyper_sphere.py +0 -0
  49. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/advanced_samples/excel_ui/(ref) original_project.femprj +0 -0
  50. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/advanced_samples/excel_ui/femtet-macro.xlsm +0 -0
  51. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/advanced_samples/excel_ui/pyfemtet-core.py +0 -0
  52. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/advanced_samples/excel_ui/test-pyfemtet-core.cmd +0 -0
  53. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_create_training_data.py +0 -0
  54. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_create_training_data_jp.py +0 -0
  55. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_optimize_with_surrogate.py +0 -0
  56. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_optimize_with_surrogate_jp.py +0 -0
  57. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_parametric.femprj +0 -0
  58. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/interface/_base.py +0 -0
  59. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/interface/_excel_interface.py +0 -0
  60. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/interface/_femtet.py +0 -0
  61. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/interface/_femtet_parametric.py +0 -0
  62. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/interface/_femtet_with_nx/__init__.py +0 -0
  63. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/interface/_femtet_with_nx/_interface.py +0 -0
  64. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/interface/_femtet_with_nx/update_model.py +0 -0
  65. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/interface/_femtet_with_sldworks.py +0 -0
  66. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/interface/_surrogate/__init__.py +0 -0
  67. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/interface/_surrogate/_chaospy.py +0 -0
  68. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/optimizer/__init__.py +0 -0
  69. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/optimizer/_base.py +0 -0
  70. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/optimizer/_optuna/__init__.py +0 -0
  71. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/optimizer/_optuna/_botorch_patch/__init__.py +0 -0
  72. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/optimizer/_optuna/_botorch_patch/enable_nonlinear_constraint.py +0 -0
  73. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/optimizer/_optuna/_optuna.py +0 -0
  74. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/optimizer/_optuna/_pof_botorch.py +0 -0
  75. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/optimizer/_scipy.py +0 -0
  76. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/optimizer/_scipy_scalar.py +0 -0
  77. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/optimizer/parameter.py +0 -0
  78. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/prediction/__init__.py +0 -0
  79. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/prediction/_base.py +0 -0
  80. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/ParametricIF.femprj +0 -0
  81. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/ParametricIF.py +0 -0
  82. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/ParametricIF_test_result.reccsv +0 -0
  83. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/cad_ex01_NX.femprj +0 -0
  84. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/cad_ex01_NX.prt +0 -0
  85. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/cad_ex01_NX.py +0 -0
  86. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/cad_ex01_NX_test_result.reccsv +0 -0
  87. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/cad_ex01_SW.SLDPRT +0 -0
  88. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/cad_ex01_SW.femprj +0 -0
  89. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/cad_ex01_SW.py +0 -0
  90. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/cad_ex01_SW_test_result.reccsv +0 -0
  91. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/constrained_pipe.femprj +0 -0
  92. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/constrained_pipe.py +0 -0
  93. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/constrained_pipe_test_result.reccsv +0 -0
  94. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/gal_ex58_parametric.femprj +0 -0
  95. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/gal_ex58_parametric.py +0 -0
  96. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/gal_ex58_parametric_test_result.reccsv +0 -0
  97. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/gau_ex08_parametric.femprj +0 -0
  98. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/gau_ex08_parametric.py +0 -0
  99. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/gau_ex08_parametric_test_result.reccsv +0 -0
  100. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/her_ex40_parametric.femprj +0 -0
  101. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/her_ex40_parametric.py +0 -0
  102. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/her_ex40_parametric_test_result.reccsv +0 -0
  103. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/paswat_ex1_parametric.femprj +0 -0
  104. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/paswat_ex1_parametric.py +0 -0
  105. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/paswat_ex1_parametric_parallel.py +0 -0
  106. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/paswat_ex1_parametric_test_result.reccsv +0 -0
  107. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/wat_ex14_parametric.femprj +0 -0
  108. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/wat_ex14_parametric.py +0 -0
  109. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/wat_ex14_parametric_parallel.py +0 -0
  110. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample/wat_ex14_parametric_test_result.reccsv +0 -0
  111. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample_jp/ParametricIF_jp.femprj +0 -0
  112. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample_jp/ParametricIF_jp.py +0 -0
  113. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample_jp/cad_ex01_NX_jp.femprj +0 -0
  114. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample_jp/cad_ex01_NX_jp.py +0 -0
  115. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample_jp/cad_ex01_SW_jp.femprj +0 -0
  116. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample_jp/cad_ex01_SW_jp.py +0 -0
  117. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample_jp/constrained_pipe_jp.py +0 -0
  118. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample_jp/gal_ex58_parametric_jp.femprj +0 -0
  119. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample_jp/gal_ex58_parametric_jp.py +0 -0
  120. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample_jp/gau_ex08_parametric_jp.femprj +0 -0
  121. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample_jp/gau_ex08_parametric_jp.py +0 -0
  122. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample_jp/her_ex40_parametric_jp.femprj +0 -0
  123. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample_jp/her_ex40_parametric_jp.py +0 -0
  124. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample_jp/paswat_ex1_parametric_jp.femprj +0 -0
  125. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample_jp/paswat_ex1_parametric_jp.py +0 -0
  126. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample_jp/paswat_ex1_parametric_parallel_jp.py +0 -0
  127. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample_jp/wat_ex14_parametric_jp.femprj +0 -0
  128. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample_jp/wat_ex14_parametric_jp.py +0 -0
  129. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/samples/femprj_sample_jp/wat_ex14_parametric_parallel_jp.py +0 -0
  130. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/__init__.py +0 -0
  131. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/_complex_components/__init__.py +0 -0
  132. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/_complex_components/alert_region.py +0 -0
  133. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/_complex_components/main_figure_creator.py +0 -0
  134. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/_complex_components/pm_graph_creator.py +0 -0
  135. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/_create_wrapped_components.py +0 -0
  136. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/_process_monitor/__init__.py +0 -0
  137. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/_wrapped_components/__init__.py +0 -0
  138. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/_wrapped_components/dbc.py +0 -0
  139. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/_wrapped_components/dcc.py +0 -0
  140. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/_wrapped_components/html.py +0 -0
  141. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/_wrapped_components/str_enum.py +0 -0
  142. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/result_viewer/.gitignore +0 -0
  143. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/result_viewer/__init__.py +0 -0
  144. {pyfemtet-0.8.4 → pyfemtet-0.8.6}/pyfemtet/opt/visualization/result_viewer/application.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pyfemtet
3
- Version: 0.8.4
3
+ Version: 0.8.6
4
4
  Summary: Design parameter optimization using Femtet.
5
5
  License: BSD-3-Clause
6
6
  Author: kazuma.naito
@@ -0,0 +1 @@
1
+ __version__ = "0.8.6"
@@ -27,6 +27,7 @@ from pyfemtet.opt._femopt_core import (
27
27
  History,
28
28
  OptimizationStatus,
29
29
  logger,
30
+ MonitorHostRecord,
30
31
  )
31
32
  from pyfemtet._message import Msg, encoding
32
33
  from pyfemtet.opt.optimizer.parameter import Parameter, Expression
@@ -135,6 +136,7 @@ class FEMOpt:
135
136
  self.monitor_process_future = None
136
137
  self.monitor_server_kwargs = dict()
137
138
  self.monitor_process_worker_name = None
139
+ self.monitor_host_record = None
138
140
  self._hv_reference = None
139
141
  self._extra_space_dir = None
140
142
 
@@ -403,7 +405,7 @@ class FEMOpt:
403
405
 
404
406
  if names is not None:
405
407
  if isinstance(names, str):
406
- names = [f'name_{i}' for i in range(n_return)]
408
+ names = [f'{names}_{i}' for i in range(n_return)]
407
409
  else:
408
410
  # names = names
409
411
  pass
@@ -679,11 +681,11 @@ class FEMOpt:
679
681
  # ===== fem の設定 ==--=
680
682
 
681
683
  # Femtet 特有の処理
682
- metadata = None
684
+ extra_data = dict()
683
685
  if isinstance(self.fem, FemtetInterface):
684
686
 
685
687
  # 結果 csv に記載する femprj に関する情報の作成
686
- metadata = json.dumps(
688
+ extra_data.update(
687
689
  dict(
688
690
  femprj_path=self.fem.original_femprj_path,
689
691
  model_name=self.fem.model_name
@@ -774,23 +776,25 @@ class FEMOpt:
774
776
 
775
777
  with self.client.cluster as _cluster, self.client as _client:
776
778
 
777
- # actor の設定
779
+ # ===== status actor の設定 =====
778
780
  self.status = OptimizationStatus(_client, worker_address=self.monitor_process_worker_name)
779
781
  self.worker_status_list = [OptimizationStatus(_client, worker_address=self.monitor_process_worker_name, name=name) for name in worker_addresses] # tqdm 検討
780
782
  self.status.set(OptimizationStatus.SETTING_UP)
783
+ self.monitor_host_record = MonitorHostRecord(_client, self.monitor_process_worker_name)
784
+ logger.info('Status Actor initialized successfully.')
785
+
786
+ # ===== initialize history =====
781
787
  self.history = History(
782
788
  self.history_path,
783
789
  self.opt.variables.get_parameter_names(),
784
790
  list(self.opt.objectives.keys()),
785
791
  list(self.opt.constraints.keys()),
786
792
  _client,
787
- metadata,
788
793
  self._hv_reference
789
794
  )
790
- logger.info('Status Actor initialized successfully.')
791
795
 
796
+ # ===== launch monitor =====
792
797
  # launch monitor
793
- # noinspection PyTypeChecker
794
798
  self.monitor_process_future = _client.submit(
795
799
  # func
796
800
  _start_monitor_server,
@@ -799,6 +803,7 @@ class FEMOpt:
799
803
  self.status,
800
804
  worker_addresses,
801
805
  self.worker_status_list,
806
+ self.monitor_host_record,
802
807
  # kwargs
803
808
  **self.monitor_server_kwargs,
804
809
  # kwargs of submit
@@ -807,6 +812,16 @@ class FEMOpt:
807
812
  )
808
813
  logger.info('Process monitor initialized successfully.')
809
814
 
815
+ # update extra_data of history to notify
816
+ # how to emit interruption signal by
817
+ # external processes
818
+ start = time()
819
+ while len(self.monitor_host_record.get()) == 0:
820
+ sleep(0.1)
821
+ extra_data.update(self.monitor_host_record.get())
822
+ self.history.extra_data.update(extra_data)
823
+
824
+ # ===== setup fem and opt before parallelization =====
810
825
  # fem
811
826
  self.fem._setup_before_parallel(_client)
812
827
 
@@ -817,6 +832,11 @@ class FEMOpt:
817
832
  self.opt.history = self.history
818
833
  self.opt._setup_before_parallel()
819
834
 
835
+ # ===== 最適化ループ開始 =====
836
+ # opt から non-serializable な com を
837
+ # 有している可能性のある fem を削除
838
+ # ただし main process の sub thread では
839
+ # これをそのまま使うので buff に退避
820
840
  buff = self.opt.fem
821
841
  del self.opt.fem
822
842
 
@@ -832,8 +852,12 @@ class FEMOpt:
832
852
  allow_other_workers=False,
833
853
  )
834
854
 
855
+ # 退避した fem を戻す
835
856
  self.opt.fem = buff
836
857
 
858
+ # リモートクラスタではない場合
859
+ # main process の sub thread で
860
+ # 計算開始
837
861
  t_main = None
838
862
  if not self.opt.is_cluster:
839
863
  # ローカルプロセスでの計算(opt._run 相当の処理)
@@ -857,7 +881,7 @@ class FEMOpt:
857
881
  )
858
882
  t_main.start()
859
883
 
860
- # save history
884
+ # ===== save history during optimization =====
861
885
  def save_history():
862
886
  while True:
863
887
  sleep(2)
@@ -872,7 +896,6 @@ class FEMOpt:
872
896
  t_save_history.start()
873
897
 
874
898
  # ===== 終了 =====
875
-
876
899
  # クラスターの Unexpected Exception のリストを取得
877
900
  opt_exceptions: list[Exception or None] = _client.gather(calc_futures) # gather() で終了待ちも兼ねる
878
901
 
@@ -884,7 +907,7 @@ class FEMOpt:
884
907
  local_opt_exception = self.opt._exception # Exception を取得
885
908
  opt_exceptions.append(local_opt_exception)
886
909
 
887
- # 終了
910
+ # 終了シグナルを送る
888
911
  self.status.set(OptimizationStatus.TERMINATED)
889
912
  end = time()
890
913
 
@@ -910,6 +933,8 @@ class FEMOpt:
910
933
  print()
911
934
 
912
935
  # monitor worker を残してユーザーが結果を確認できるようにする
936
+ # with 文を抜けると monitor worker が終了して
937
+ # daemon thread である run_forever が終了する
913
938
  if confirm_before_exit:
914
939
  print()
915
940
  print('='*len(Msg.CONFIRM_BEFORE_EXIT))
@@ -945,6 +970,7 @@ def _start_monitor_server(
945
970
  status,
946
971
  worker_addresses,
947
972
  worker_status_list,
973
+ host_record,
948
974
  host=None,
949
975
  port=None,
950
976
  ):
@@ -955,5 +981,6 @@ def _start_monitor_server(
955
981
  worker_status_list,
956
982
  host,
957
983
  port,
984
+ host_record,
958
985
  )
959
986
  return 'Exit monitor server process gracefully'
@@ -1,4 +1,5 @@
1
1
  # typing
2
+ import json
2
3
  from typing import List, TYPE_CHECKING
3
4
 
4
5
  # built-in
@@ -524,7 +525,6 @@ class History:
524
525
  obj_names (List[str], optional): The names of objectives. Defaults to None.
525
526
  cns_names (List[str], optional): The names of constraints. Defaults to None.
526
527
  client (dask.distributed.Client): Dask client.
527
- additional_metadata (str, optional): metadata of optimization process.
528
528
  hv_reference (str or list[float or np.ndarray, optional):
529
529
  The method to calculate hypervolume or
530
530
  the reference point itself.
@@ -550,7 +550,6 @@ class History:
550
550
  obj_names=None,
551
551
  cns_names=None,
552
552
  client=None,
553
- additional_metadata=None,
554
553
  hv_reference=None,
555
554
  ):
556
555
  # hypervolume 計算メソッド
@@ -561,7 +560,8 @@ class History:
561
560
  self.prm_names = prm_names
562
561
  self.obj_names = obj_names
563
562
  self.cns_names = cns_names
564
- self.additional_metadata = additional_metadata or ''
563
+ self.extra_data = dict()
564
+ self.meta_columns = None
565
565
  self.__scheduler_address = client.scheduler.address if client is not None else None
566
566
 
567
567
  # 最適化実行中かどうか
@@ -575,15 +575,15 @@ class History:
575
575
 
576
576
  # 続きからなら df を読み込んで df にコピー
577
577
  if self.is_restart:
578
- self.load()
578
+ self.load() # 中で meta_columns を読む
579
579
 
580
580
  # そうでなければ df を初期化
581
581
  else:
582
- columns, metadata = self.create_df_columns()
582
+ columns, meta_columns = self.create_df_columns()
583
583
  df = pd.DataFrame()
584
584
  for c in columns:
585
585
  df[c] = None
586
- self.metadata = metadata
586
+ self.meta_columns = meta_columns
587
587
  self.set_df(df)
588
588
 
589
589
  # 一時ファイルに書き込みを試み、UnicodeEncodeError が出ないかチェック
@@ -609,16 +609,16 @@ class History:
609
609
  # df を読み込む
610
610
  df = pd.read_csv(self.path, encoding=self.ENCODING, header=self.HEADER_ROW)
611
611
 
612
- # metadata を読み込む
612
+ # meta_columns を読み込む
613
613
  with open(self.path, mode='r', encoding=self.ENCODING, newline='\n') as f:
614
614
  reader = csv.reader(f, delimiter=',')
615
- self.metadata = reader.__next__()
615
+ self.meta_columns = reader.__next__()
616
616
 
617
617
  # 最適化問題を読み込む
618
618
  columns = df.columns
619
- prm_names = [column for i, column in enumerate(columns) if self.metadata[i] == 'prm']
620
- obj_names = [column for i, column in enumerate(columns) if self.metadata[i] == 'obj']
621
- cns_names = [column for i, column in enumerate(columns) if self.metadata[i] == 'cns']
619
+ prm_names = [column for i, column in enumerate(columns) if self.meta_columns[i] == 'prm']
620
+ obj_names = [column for i, column in enumerate(columns) if self.meta_columns[i] == 'obj']
621
+ cns_names = [column for i, column in enumerate(columns) if self.meta_columns[i] == 'cns']
622
622
 
623
623
  # is_restart の場合、読み込んだ names と引数の names が一致するか確認しておく
624
624
  if self.is_restart:
@@ -662,7 +662,7 @@ class History:
662
662
  logger.debug('Access df of History before it is initialized.')
663
663
  return pd.DataFrame()
664
664
  except OSError:
665
- logger.error('Scheduler is already dead. Most frequent reasen to show this message is that the pyfemtet monitor UI is not refreshed even if the main optimization process is terminated.')
665
+ logger.error('Scheduler is already dead. Most frequent reason to show this message is that the pyfemtet monitor UI is not refreshed even if the main optimization process is terminated.')
666
666
  return pd.DataFrame()
667
667
 
668
668
  def set_df(self, df: pd.DataFrame):
@@ -687,46 +687,46 @@ class History:
687
687
  columns = list()
688
688
 
689
689
  # columns のメタデータを作成
690
- metadata = list()
690
+ meta_columns = list()
691
691
 
692
692
  # trial
693
693
  columns.append('trial') # index
694
- metadata.append(self.additional_metadata)
694
+ meta_columns.append('') # extra_data. save 時に中身を記入する。
695
695
 
696
696
  # parameter
697
697
  for prm_name in self.prm_names:
698
698
  columns.extend([prm_name, prm_name + '_lower_bound', prm_name + '_upper_bound'])
699
- metadata.extend(['prm', 'prm_lb', 'prm_ub'])
699
+ meta_columns.extend(['prm', 'prm_lb', 'prm_ub'])
700
700
 
701
701
  # objective relative
702
702
  for name in self.obj_names:
703
703
  columns.append(name)
704
- metadata.append('obj')
704
+ meta_columns.append('obj')
705
705
  columns.append(name + '_direction')
706
- metadata.append('obj_direction')
706
+ meta_columns.append('obj_direction')
707
707
  columns.append('non_domi')
708
- metadata.append('')
708
+ meta_columns.append('')
709
709
 
710
710
  # constraint relative
711
711
  for name in self.cns_names:
712
712
  columns.append(name)
713
- metadata.append('cns')
713
+ meta_columns.append('cns')
714
714
  columns.append(name + '_lower_bound')
715
- metadata.append('cns_lb')
715
+ meta_columns.append('cns_lb')
716
716
  columns.append(name + '_upper_bound')
717
- metadata.append('cns_ub')
717
+ meta_columns.append('cns_ub')
718
718
  columns.append('feasible')
719
- metadata.append('')
719
+ meta_columns.append('')
720
720
 
721
721
  # the others
722
722
  columns.append('hypervolume')
723
- metadata.append('')
723
+ meta_columns.append('')
724
724
  columns.append('message')
725
- metadata.append('')
725
+ meta_columns.append('')
726
726
  columns.append('time')
727
- metadata.append('')
727
+ meta_columns.append('')
728
728
 
729
- return columns, metadata
729
+ return columns, meta_columns
730
730
 
731
731
  def record(
732
732
  self,
@@ -973,13 +973,16 @@ class History:
973
973
 
974
974
  df = self.get_df()
975
975
 
976
+ # extra_data の更新
977
+ self.meta_columns[0] = json.dumps(self.extra_data)
978
+
976
979
  if _f is None:
977
980
  # save df with columns with prefix
978
981
  with open(self.path, 'w', encoding=self.ENCODING) as f:
979
982
  writer = csv.writer(f, delimiter=',', lineterminator="\n")
980
- writer.writerow(self.metadata)
983
+ writer.writerow(self.meta_columns)
981
984
  for i in range(self.HEADER_ROW-1):
982
- writer.writerow([''] * len(self.metadata))
985
+ writer.writerow([''] * len(self.meta_columns))
983
986
  df.to_csv(f, index=None, encoding=self.ENCODING, lineterminator='\n')
984
987
  else: # test
985
988
  df.to_csv(_f, index=None, encoding=self.ENCODING, lineterminator='\n')
@@ -1088,3 +1091,35 @@ class OptimizationStatus:
1088
1091
  def get_text(self) -> str:
1089
1092
  """Get optimization status message."""
1090
1093
  return self._actor.status
1094
+
1095
+
1096
+ class _MonitorHostRecordActor:
1097
+ host = None
1098
+ port = None
1099
+
1100
+ def set(self, host, port):
1101
+ self.host = host
1102
+ self.port = port
1103
+
1104
+
1105
+ class MonitorHostRecord:
1106
+
1107
+ def __init__(self, client, worker_name):
1108
+ self._future = client.submit(
1109
+ _MonitorHostRecordActor,
1110
+ actor=True,
1111
+ workers=(worker_name,),
1112
+ allow_other_workers=False,
1113
+ )
1114
+ self._actor = self._future.result()
1115
+
1116
+ def set(self, host, port):
1117
+ self._actor.set(host, port).result()
1118
+
1119
+ def get(self):
1120
+ host = self._actor.host
1121
+ port = self._actor.port
1122
+ if host is None and port is None:
1123
+ return dict()
1124
+ else:
1125
+ return dict(host=host, port=port)
@@ -10,7 +10,7 @@ from pyfemtet.opt import FEMOpt
10
10
  from pyfemtet._message import encoding as ENCODING
11
11
 
12
12
 
13
- def remove_femprj_metadata_from_csv(csv_path, encoding=ENCODING):
13
+ def remove_extra_data_from_csv(csv_path, encoding=ENCODING):
14
14
 
15
15
  with open(csv_path, mode="r", encoding=encoding, newline="\n") as f:
16
16
  reader = csv.reader(f, delimiter=",")
@@ -59,32 +59,39 @@ def _get_obj_from_csv(csv_path, encoding=ENCODING):
59
59
  reader = csv.reader(f, delimiter=",")
60
60
  meta = reader.__next__()
61
61
  obj_indices = np.where(np.array(meta) == "obj")[0]
62
- out = df.iloc[:, obj_indices]
62
+ out: pd.DataFrame = df.iloc[:, obj_indices]
63
+ out = out.dropna(axis=0)
63
64
  return out, columns
64
65
 
65
66
 
66
- def is_equal_result(ref_path, dif_path, log_path):
67
+ def is_equal_result(ref_path, dif_path, log_path=None, threashold=0.05):
67
68
  """Check the equality of two result csv files."""
68
69
  ref_df, ref_columns = _get_obj_from_csv(ref_path)
69
70
  dif_df, dif_columns = _get_obj_from_csv(dif_path)
70
71
 
71
- with open(log_path, "a", newline="\n", encoding=ENCODING) as f:
72
- f.write("\n\n===== 結果の分析 =====\n\n")
73
- f.write(f" \tref\tdif\n")
74
- f.write(f"---------------------\n")
75
- f.write(f"len(col)\t{len(ref_columns)}\t{len(dif_columns)}\n")
76
- f.write(f"len(df) \t{len(ref_df)}\t{len(dif_df)}\n")
77
- try:
78
- difference = (
72
+ if log_path is not None:
73
+ with open(log_path, "a", newline="\n", encoding=ENCODING) as f:
74
+ f.write("\n\n===== 結果の分析 =====\n\n")
75
+ f.write(f" \tref\tdif\n")
76
+ f.write(f"---------------------\n")
77
+ f.write(f"len(col)\t{len(ref_columns)}\t{len(dif_columns)}\n")
78
+ f.write(f"len(df) \t{len(ref_df)}\t{len(dif_df)}\n")
79
+ try:
80
+ difference = (
81
+ np.abs(ref_df.values - dif_df.values) / np.abs(dif_df.values)
82
+ ).mean()
83
+ f.write(f"diff \t{int(difference*100)}%\n")
84
+ except Exception:
85
+ f.write(f"diff \tcannot calc\n")
86
+
87
+ else:
88
+ difference = (
79
89
  np.abs(ref_df.values - dif_df.values) / np.abs(dif_df.values)
80
- ).mean()
81
- f.write(f"diff \t{int(difference*100)}%\n")
82
- except Exception:
83
- f.write(f"diff \tcannot calc\n")
90
+ ).mean()
84
91
 
85
92
  assert len(ref_columns) == len(dif_columns), "結果 csv の column 数が異なります。"
86
93
  assert len(ref_df) == len(dif_df), "結果 csv の row 数が異なります。"
87
- assert difference <= 0.05, "前回の結果との平均差異が 5% を超えています。"
94
+ assert difference <= threashold*100, f"前回の結果との平均差異が {int(difference)}% で {int(threashold*100)}% を超えています。"
88
95
 
89
96
 
90
97
  def _get_simplified_df_values(csv_path, exclude_columns=None):
@@ -21,7 +21,9 @@ else:
21
21
  FemtetWithNXInterface = type('FemtetWithNXInterface', (FemtetInterface,), {})
22
22
  ExcelInterface = type('FemtetInterface', (NotAvailableForWindows,), {})
23
23
 
24
- from pyfemtet.opt.interface._surrogate import PoFBoTorchInterface
24
+ from pyfemtet.opt.interface._surrogate._base import SurrogateModelInterfaceBase
25
+ from pyfemtet.opt.interface._surrogate._singletaskgp import PoFBoTorchInterface
26
+
25
27
 
26
28
  __all__ =[
27
29
  'FEMInterface',
@@ -30,5 +32,6 @@ __all__ =[
30
32
  'FemtetWithSolidworksInterface',
31
33
  'FemtetWithNXInterface',
32
34
  'ExcelInterface',
35
+ 'SurrogateModelInterfaceBase',
33
36
  'PoFBoTorchInterface',
34
37
  ]
@@ -17,6 +17,7 @@ class SurrogateModelInterfaceBase(FEMInterface, ABC):
17
17
  self,
18
18
  history_path: str = None,
19
19
  history: History = None,
20
+ override_objective: bool = True,
20
21
  ):
21
22
 
22
23
  self.history: History
@@ -25,6 +26,7 @@ class SurrogateModelInterfaceBase(FEMInterface, ABC):
25
26
  self.obj: dict[str, float] = dict()
26
27
  self.df_prm: pd.DataFrame
27
28
  self.df_obj: pd.DataFrame
29
+ self.override_objective: bool = override_objective
28
30
 
29
31
  # history_path が与えられた場合、history をコンストラクトする
30
32
  if history_path is not None:
@@ -57,27 +59,25 @@ class SurrogateModelInterfaceBase(FEMInterface, ABC):
57
59
  FEMInterface.__init__(
58
60
  self,
59
61
  history=history, # コンストラクト済み history を渡せば並列計算時も何もしなくてよい
62
+ override_objective=self.override_objective
60
63
  )
61
64
 
62
65
  def filter_feasible(self, x: np.ndarray, y: np.ndarray, return_feasibility=False):
63
66
  feasible_idx = np.where(~np.isnan(y.sum(axis=1)))
64
67
  if return_feasibility:
65
68
  # calculated or not
66
- y = np.zeros_like(y)
67
- y[feasible_idx] = 1.
68
- # satisfy weak feasibility or not
69
- infeasible_idx = np.where(~self.history.get_df()['feasible'].values)
70
- y[infeasible_idx] = .0
71
- return x, y.reshape((-1, 1))
69
+ feas = np.zeros((len(y), 1), dtype=float)
70
+ feas[feasible_idx] = 1.
71
+ return x, feas
72
72
  else:
73
73
  return x[feasible_idx], y[feasible_idx]
74
74
 
75
75
  def _setup_after_parallel(self, *args, **kwargs):
76
-
77
- opt: AbstractOptimizer = kwargs['opt']
78
- obj: Objective
79
- for obj_name, obj in opt.objectives.items():
80
- obj.fun = lambda: self.obj[obj_name]
76
+ if self.override_objective:
77
+ opt: AbstractOptimizer = kwargs['opt']
78
+ obj: Objective
79
+ for obj_name, obj in opt.objectives.items():
80
+ obj.fun = lambda obj_name_=obj_name: self.obj[obj_name_]
81
81
 
82
82
  def update_parameter(self, parameters: pd.DataFrame, with_warning=False) -> Optional[List[str]]:
83
83
  for i, row in parameters.iterrows():
@@ -27,8 +27,8 @@ class PoFBoTorchInterface(SurrogateModelInterfaceBase):
27
27
  def train_f(self):
28
28
  # df そのまま用いて training する
29
29
  x, y = self.filter_feasible(self.df_prm.values, self.df_obj.values, return_feasibility=True)
30
- if y.min() == 1:
31
- self.model_f.predict = lambda *args, **kwargs: (1., 0.001)
30
+ if y.min() == 1: # feasible values only
31
+ self.model_f.predict = lambda *args, **kwargs: (1., 0.001) # mean, std
32
32
  self.model_f.fit(x, y)
33
33
 
34
34
  def _setup_after_parallel(self, *args, **kwargs):
@@ -64,7 +64,8 @@ class PoFBoTorchInterface(SurrogateModelInterfaceBase):
64
64
  raise SolveError(Msg.INFO_POF_IS_LESS_THAN_THRESHOLD)
65
65
 
66
66
  # 実際の計算(mean は history.obj_names 順)
67
- mean, _ = self.model.predict(np.array([x]))
67
+ _mean, _std = self.model.predict(np.array([x]))
68
+ mean = _mean[0]
68
69
 
69
70
  # 目的関数の更新
70
71
  self.obj = {obj_name: value for obj_name, value in zip(self.history.obj_names, mean)}
@@ -42,16 +42,16 @@ class SingleTaskGPModel(PredictionModelBase):
42
42
  def set_bounds_from_history(self, history, df=None):
43
43
  from pyfemtet.opt._femopt_core import History
44
44
  history: History
45
- metadata: str
45
+ meta_column: str
46
46
 
47
47
  if df is None:
48
48
  df = history.get_df()
49
49
 
50
50
  columns = df.columns
51
- metadata_columns = history.metadata
51
+
52
52
  target_columns = [
53
- col for col, metadata in zip(columns, metadata_columns)
54
- if metadata == 'prm_lb' or metadata == 'prm_ub'
53
+ col for col, meta_column in zip(columns, history.meta_columns)
54
+ if meta_column == 'prm_lb' or meta_column == 'prm_ub'
55
55
  ]
56
56
 
57
57
  bounds_buff = df.iloc[0][target_columns].values # 2*len(prm_names) array
@@ -85,6 +85,8 @@ class SingleTaskGPModel(PredictionModelBase):
85
85
  fit_gpytorch_mll(mll)
86
86
 
87
87
  def predict(self, x: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
88
+ assert len(x.shape) >= 2
89
+
88
90
  X = tensor(x)
89
91
 
90
92
  post = self.gp.posterior(X)
@@ -2,6 +2,7 @@
2
2
  from dash.development.base_component import Component
3
3
 
4
4
  # application
5
+ from flask import Flask
5
6
  from dash import Dash
6
7
  import webbrowser
7
8
 
@@ -20,6 +21,7 @@ from pyfemtet.opt.visualization._wrapped_components import html, dcc, dbc
20
21
  from abc import ABC, abstractmethod
21
22
  import logging
22
23
  import psutil
24
+ import json
23
25
  from pyfemtet.logger import get_module_logger, get_dash_logger
24
26
 
25
27
  logger = get_module_logger('opt.monitor', __name__)
@@ -132,15 +134,19 @@ class SidebarApplicationBase:
132
134
  # define app
133
135
  self.title = title if title is not None else 'App'
134
136
  self.subtitle = subtitle if title is not None else ''
137
+ self.server = Flask(__name__)
135
138
  self.app = Dash(
136
139
  __name__,
137
140
  external_stylesheets=[dash_bootstrap_components.themes.BOOTSTRAP],
138
141
  title=title,
139
142
  update_title=None,
143
+ server=self.server,
140
144
  )
141
145
  self.pages = dict()
142
146
  self.nav_links = dict()
143
147
  self.page_objects = []
148
+ self.host = None
149
+ self.port = None
144
150
 
145
151
  def add_page(self, page: AbstractPage, order: int = None):
146
152
  page.set_application(self)
@@ -191,7 +197,7 @@ class SidebarApplicationBase:
191
197
  className="p-3 bg-light rounded-3",
192
198
  )
193
199
 
194
- def run(self, host='localhost', port=None, debug=False):
200
+ def run(self, host='localhost', port=None, debug=False, host_record=None):
195
201
  self._setup_layout()
196
202
  port = port or self.DEFAULT_PORT
197
203
  # port を検証
@@ -201,6 +207,11 @@ class SidebarApplicationBase:
201
207
  webbrowser.open(f'http://localhost:{str(port)}')
202
208
  else:
203
209
  webbrowser.open(f'http://{host}:{str(port)}')
210
+ self.host = host
211
+ self.port = port
212
+ if host_record is not None:
213
+ host_record.set(self.host, self.port)
214
+
204
215
  self.app.run(debug=debug, host=host, port=port)
205
216
 
206
217
 
@@ -138,18 +138,18 @@ class FemtetControl(AbstractPage):
138
138
 
139
139
  # check holding history
140
140
  if self.application.history is None:
141
- return kwargs, Msg.ERR_HISTORY_CSV_NOT_READ
141
+ return kwargs, Msg.WARN_HISTORY_CSV_NOT_READ
142
142
 
143
- # get metadata
144
- additional_metadata = self.application.history.metadata[0]
143
+ # get extra_data
144
+ extra_data = self.application.history.meta_columns[0]
145
145
 
146
- # check metadata exists
147
- if additional_metadata == '':
146
+ # check extra_data exists
147
+ if extra_data == '':
148
148
  return kwargs, Msg.WARN_INVALID_METADATA
149
149
 
150
- # check the metadata is valid json
150
+ # check the extra_data is valid json
151
151
  try:
152
- d = json.loads(additional_metadata)
152
+ d = json.loads(extra_data)
153
153
  femprj_path = os.path.abspath(d['femprj_path'])
154
154
  except (TypeError, json.decoder.JSONDecodeError, KeyError):
155
155
  return kwargs, Msg.WARN_INVALID_METADATA