@@ -68,6 +68,10 @@ def __init__(
6868
6969 self .server = get_server ()
7070
71+ # initialize include upload value: False (bottom sheet with include upload is not displayed until there is a fourcyaml file uploaded)
72+ self .state .include_upload_open = False
73+ self .state .included_files = []
74+
7175 # declare server-side variable dict: variables which should not
7276 # be exposed to the client-side
7377 self ._server_vars = {}
@@ -120,18 +124,11 @@ def __init__(
120124 # initialize state object
121125 self .init_state_and_server_vars ()
122126
123- # convert file to vtu and create dedicated render objects
124- fourc_geometry = FourCGeometry (
125- fourc_yaml_file = fourc_yaml_file ,
126- temp_dir = Path (self ._server_vars ["temp_dir_object" ].name ),
127- )
128- self .state .vtu_path = fourc_geometry .vtu_file_path
127+ if "render_window" not in self ._actors :
128+ self ._server_vars ["render_window" ] = pv .Plotter ()
129+ self .state .vtu_path = ""
129130
130- if self .state .vtu_path == "" :
131- self .state .read_in_status = self .state .all_read_in_statuses [
132- "vtu_conversion_error"
133- ]
134- self .init_pyvista_render_objects ()
131+ self ._server_vars ["fourc_yaml_file_dir" ] = Path (fourc_yaml_file ).parent
135132
136133 # create ui
137134 create_gui (self .server , self ._server_vars ["render_window" ])
@@ -267,11 +264,57 @@ def init_pyvista_render_objects(self):
267264
268265 The saved vtu file path is hereby utilized.
269266 """
270- if "render_window" not in self ._actors :
271- self ._server_vars ["render_window" ] = pv .Plotter ()
267+ # convert file to vtu and create dedicated render objects
268+ if not Path (
269+ self ._server_vars ["temp_dir_object" ].name
270+ + "\\ "
271+ + self ._server_vars ["fourc_yaml_name" ]
272+ ).exists ():
273+ raise Exception (
274+ "File does not exist: "
275+ + self ._server_vars ["temp_dir_object" ].name
276+ + "\\ "
277+ + self ._server_vars ["fourc_yaml_name" ]
278+ )
279+ geometry_file_name = (
280+ self ._server_vars ["fourc_yaml_content" ]
281+ .sections .get ("STRUCTURE GEOMETRY" , {})
282+ .get ("FILE" )
283+ )
284+ if geometry_file_name :
285+ if not Path (
286+ self ._server_vars ["temp_dir_object" ].name
287+ + "\\ "
288+ + Path (
289+ self ._server_vars ["fourc_yaml_content" ]
290+ .sections .get ("STRUCTURE GEOMETRY" , {})
291+ .get ("FILE" )
292+ ).name
293+ ).exists ():
294+ raise Exception (
295+ "File does not exist: "
296+ + self ._server_vars ["temp_dir_object" ].name
297+ + "\\ "
298+ + Path (
299+ self ._server_vars ["fourc_yaml_content" ]["STRUCTURE GEOMETRY" ][
300+ "FILE"
301+ ]
302+ ).name
303+ )
304+ fourc_geometry = FourCGeometry (
305+ fourc_yaml_file = self ._server_vars ["temp_dir_object" ].name
306+ + "\\ "
307+ + self ._server_vars ["fourc_yaml_name" ],
308+ temp_dir = Path (self ._server_vars ["temp_dir_object" ].name ),
309+ )
310+ self .state .vtu_path = fourc_geometry .vtu_file_path
272311
273- self ._server_vars ["render_window" ].clear_actors ()
312+ if self .state .vtu_path == "" :
313+ self .state .read_in_status = self .state .all_read_in_statuses [
314+ "vtu_conversion_error"
315+ ]
274316
317+ self ._server_vars ["render_window" ].clear_actors ()
275318 problem_mesh = pv .read (self .state .vtu_path )
276319 # get problem mesh
277320 self ._actors ["problem_mesh" ] = self ._server_vars ["render_window" ].add_mesh (
@@ -334,6 +377,12 @@ def init_pyvista_render_objects(self):
334377 all_result_descriptions = self .state .result_description_section .keys ()
335378
336379 for dc in all_result_descriptions :
380+ if (
381+ not self .state .result_description_section [dc ]
382+ .get ("PARAMETERS" , {})
383+ .get ("NODE" )
384+ ):
385+ continue
337386 node_coords = problem_mesh .points [
338387 self .state .result_description_section [dc ]["PARAMETERS" ]["NODE" ] - 1 ,
339388 :,
@@ -351,6 +400,8 @@ def init_pyvista_render_objects(self):
351400 )
352401 self .update_pyvista_render_objects ()
353402
403+ self ._server_vars ["render_window" ].reset_camera ()
404+
354405 def update_pyvista_render_objects (self ):
355406 """Update/ initialize pyvista view objects (reader, thresholds, global
356407 COS, ...) for the rendered window.
@@ -359,7 +410,7 @@ def update_pyvista_render_objects(self):
359410 """
360411 legend_items = []
361412
362- for dc in self ._actors [ "result_description_nodes" ] .values ():
413+ for dc in self ._actors . get ( "result_description_nodes" , {}) .values ():
363414 dc .SetVisibility (False )
364415 if (
365416 self .state .selected_main_section_name == "RESULT DESCRIPTION"
@@ -372,7 +423,7 @@ def update_pyvista_render_objects(self):
372423 ].SetVisibility (True )
373424 legend_items .append (("Selected result description" , "deepskyblue" ))
374425
375- for rd in self ._actors [ "dc_geometry_entities" ] .values ():
426+ for rd in self ._actors . get ( "dc_geometry_entities" , {}) .values ():
376427 rd .SetVisibility (False )
377428 if (
378429 self .state .selected_main_section_name == "DESIGN CONDITIONS"
@@ -384,7 +435,7 @@ def update_pyvista_render_objects(self):
384435 ].SetVisibility (True )
385436 legend_items .append (("Selected design condition" , "navy" ))
386437
387- for mat in self ._actors [ "material_meshes" ] .values ():
438+ for mat in self ._actors . get ( "material_meshes" , {}) .values ():
388439 mat .SetVisibility (False )
389440 if (
390441 self .state .selected_material
@@ -743,7 +794,9 @@ def init_result_description_state_and_server_vars(self):
743794
744795 # get result description section
745796 result_description_section = copy .deepcopy (
746- self ._server_vars ["fourc_yaml_content" ]["RESULT DESCRIPTION" ]
797+ self ._server_vars ["fourc_yaml_content" ].sections .get (
798+ "RESULT DESCRIPTION" , {}
799+ )
747800 )
748801
749802 # initialize empty dict as the result description section
@@ -913,6 +966,10 @@ def init_funct_state_and_server_vars(self):
913966 all_contained_var_names = get_variable_names_in_funct_expression (
914967 item_data ["SYMBOLIC_FUNCTION_OF_SPACE_TIME" ]
915968 )
969+ if "e" in all_contained_var_names :
970+ all_contained_var_names .remove ("e" )
971+ if "E" in all_contained_var_names :
972+ all_contained_var_names .remove ("E" )
916973
917974 # loop through contained variables and see whether they are evaluable
918975 for contained_var_name in all_contained_var_names :
@@ -954,6 +1011,46 @@ def init_funct_state_and_server_vars(self):
9541011 6 # precision for the user input of the values defined above: x, y, z and t_max
9551012 )
9561013
1014+ def request_included_files (self ):
1015+ """Requests the included files from the user by opening a the include
1016+ files dialog and setting up the state variable accordingly."""
1017+ included_files = []
1018+
1019+ exo_file_name = Path (
1020+ self ._server_vars .get ("fourc_yaml_content" )
1021+ .sections .get ("STRUCTURE GEOMETRY" , {})
1022+ .get ("FILE" )
1023+ or ""
1024+ ).name
1025+ if exo_file_name :
1026+ exo_file_server = Path (
1027+ self ._server_vars ["fourc_yaml_file_dir" ],
1028+ exo_file_name ,
1029+ )
1030+ exo_temp_path = Path (
1031+ self ._server_vars ["temp_dir_object" ].name ,
1032+ exo_file_name ,
1033+ )
1034+ if exo_file_server .is_file ():
1035+ with open (exo_file_server , "rb" ) as fr :
1036+ with open (exo_temp_path , "wb" ) as fw :
1037+ fw .write (fr .read ())
1038+ elif not exo_temp_path .is_file ():
1039+ included_files .append (
1040+ {
1041+ "name" : exo_file_name ,
1042+ "uploaded" : False ,
1043+ "error" : None ,
1044+ "content" : None ,
1045+ }
1046+ )
1047+
1048+ self .state .included_files = included_files
1049+ if self .state .included_files :
1050+ self .state .include_upload_open = True
1051+ else :
1052+ self .confirm_included_files ()
1053+
9571054 def sync_funct_section_from_state (self ):
9581055 """Syncs the server-side functions section based on the current values
9591056 of the dedicated state variables."""
@@ -1025,12 +1122,22 @@ def init_mode_state_vars(self):
10251122 def change_fourc_yaml_file (self , fourc_yaml_file , ** kwargs ):
10261123 """Reaction to change of state.fourc_yaml_file."""
10271124
1125+ if not fourc_yaml_file or fourc_yaml_file ["name" ].split ("." )[- 1 ] not in [
1126+ "yaml" ,
1127+ "yml" ,
1128+ "DAT" ,
1129+ "dat" ,
1130+ ]:
1131+ print (
1132+ "Warning: File does not have a .yml / .yaml / .dat / .DAT ending or is empty. Try opening another file."
1133+ )
1134+ return
10281135 # create temporary fourc yaml file from the content of the given file
10291136 temp_fourc_yaml_file = Path (
10301137 self ._server_vars ["temp_dir_object" ].name , fourc_yaml_file ["name" ]
10311138 )
1032- with open (temp_fourc_yaml_file , "w " ) as f :
1033- f .writelines (fourc_yaml_file ["content" ]. decode ( "utf-8" ) )
1139+ with open (temp_fourc_yaml_file , "wb " ) as f :
1140+ f .write (fourc_yaml_file ["content" ])
10341141
10351142 # read content, lines and other details of the given file
10361143 (
@@ -1042,12 +1149,63 @@ def change_fourc_yaml_file(self, fourc_yaml_file, **kwargs):
10421149 ) = read_fourc_yaml_file (temp_fourc_yaml_file )
10431150 self ._server_vars ["fourc_yaml_name" ] = Path (temp_fourc_yaml_file ).name
10441151
1045- # set vtu file path empty to make the convert button visible
1046- # (only if the function was not run yet, i.e., after the
1047- # initial rendering)
1048- self ._server_vars ["render_count" ]["change_fourc_yaml_file" ] += 1
1049- if self ._server_vars ["render_count" ]["change_fourc_yaml_file" ] > 1 :
1050- self .state .vtu_path = ""
1152+ if self ._server_vars ["fourc_yaml_read_in_status" ]:
1153+ self .state .read_in_status = self .state .all_read_in_statuses ["success" ]
1154+ else :
1155+ self .state .read_in_status = self .state .all_read_in_statuses [
1156+ "validation_error"
1157+ ]
1158+
1159+ self ._server_vars ["fourc_yaml_name" ] = temp_fourc_yaml_file .name
1160+
1161+ self .request_included_files ()
1162+
1163+ @controller .set ("on_upload_include_file" )
1164+ def on_upload_include_file (self , uploaded_file , index , ** kwargs ):
1165+ """Gets called when an included file is uploaded.
1166+
1167+ Saves the uploaded file into the state variable.
1168+ """
1169+ self .state .included_files [index ]["content" ] = uploaded_file
1170+
1171+ try :
1172+ if self .state .included_files [index ]["name" ] != uploaded_file ["name" ]:
1173+ self .state .included_files [index ]["error" ] = (
1174+ "File name mismatch. Expected: "
1175+ + self .state .included_files [index ]["name" ]
1176+ )
1177+ elif self .state .included_files [index ]["content" ]["size" ] == 0 :
1178+ self .state .included_files [index ]["error" ] = "File is empty."
1179+ else :
1180+ self .state .included_files [index ]["error" ] = None
1181+ self .state .included_files [index ]["uploaded" ] = True
1182+ except Exception :
1183+ self .state .included_files [index ]["error" ] = "Please upload a file."
1184+ self .state .included_files [index ]["uploaded" ] = False
1185+ self .state .dirty ("included_files" )
1186+ self .state .flush ()
1187+
1188+ @controller .set ("confirm_included_files" )
1189+ def confirm_included_files (self , ** kwargs ):
1190+ """Gets called when the Accept button in the included files dialog is
1191+ pressed.
1192+
1193+ Saves all files into the temporary directory.
1194+ """
1195+ self .state .include_upload_open = False
1196+
1197+ for included_file in self .state .included_files :
1198+ # create file in temp directory
1199+ included_file_path = Path (
1200+ self ._server_vars ["temp_dir_object" ].name ,
1201+ included_file ["content" ]["name" ],
1202+ )
1203+ with open (included_file_path , "wb" ) as f :
1204+ f .write (included_file ["content" ]["content" ])
1205+
1206+ self .init_state_and_server_vars ()
1207+
1208+ self .init_pyvista_render_objects ()
10511209
10521210 @change ("export_fourc_yaml_path" )
10531211 def change_export_fourc_yaml_path (self , export_fourc_yaml_path , ** kwargs ):
@@ -1082,7 +1240,6 @@ def change_selected_material(self, selected_material, **kwargs):
10821240 # material (if we are not in an initial rendering scenario)
10831241 if self ._server_vars ["render_count" ]["change_selected_material" ] > 0 :
10841242 # first get the master material id
1085- master_mat_id = self .determine_master_mat_ind_for_current_selection ()
10861243
10871244 # update plotter / render objects
10881245 self .update_pyvista_render_objects ()
@@ -1158,7 +1315,7 @@ def change_selected_funct(self, selected_funct, **kwargs):
11581315 # set the selected funct item to the first within the newly
11591316 # selected funct
11601317 self .state .selected_funct_item = next (
1161- iter (self .state .funct_section [ selected_funct ] )
1318+ iter (self .state .funct_section . get ( selected_funct , {}) )
11621319 )
11631320
11641321 # update plotly figure
@@ -1183,18 +1340,22 @@ def change_selected_funct_item(self, selected_funct_item, **kwargs):
11831340 def change_funct_plot (self , funct_plot , ** kwargs ):
11841341 """Reaction to change of state.funct_plot."""
11851342 # update plotly figure
1186- if self .state .funct_section [self .state .selected_funct ][
1187- self .state .selected_funct_item
1188- ]["VISUALIZATION" ]:
1343+ if (
1344+ self .state .funct_section .get (self .state .selected_funct , {})
1345+ .get (self .state .selected_funct_item , {})
1346+ .get ("VISUALIZATION" )
1347+ ):
11891348 self .server .controller .figure_update (function_plot_figure (self .state ))
11901349
11911350 @change ("funct_section" )
11921351 def change_funct_section (self , funct_section , ** kwargs ):
11931352 """Reaction to change of state.funct_section."""
11941353 # update plotly figure
1195- if self .state .funct_section [self .state .selected_funct ][
1196- self .state .selected_funct_item
1197- ]["VISUALIZATION" ]:
1354+ if (
1355+ self .state .funct_section .get (self .state .selected_funct , {})
1356+ .get (self .state .selected_funct_item , {})
1357+ .get ("VISUALIZATION" )
1358+ ):
11981359 self .server .controller .figure_update (function_plot_figure (self .state ))
11991360
12001361 #################################################
@@ -1281,12 +1442,7 @@ def click_convert_button(self, **kwargs):
12811442 # initialize state object
12821443 self .init_state_and_server_vars ()
12831444
1284- # convert to vtu
1285- fourc_geometry = FourCGeometry (
1286- fourc_yaml_file = temp_fourc_yaml_file ,
1287- temp_dir = Path (self ._server_vars ["temp_dir_object" ].name ),
1288- )
1289- self .state .vtu_path = fourc_geometry .vtu_file_path
1445+ self .init_pyvista_render_objects ()
12901446
12911447 # catch eventual conversion error
12921448 if self .state .vtu_path == "" :
0 commit comments