7
7
from rich .console import Console
8
8
from rich .traceback import install
9
9
import logging
10
+ from time import localtime , strftime
10
11
11
12
# Add root of HexMeshWorkshop project folder in path
12
13
project_root = str (Path (__file__ ).parent .parent .absolute ())
17
18
18
19
from modules .data_folder_types import *
19
20
20
- nb_CAD = 0
21
-
22
- nb_meshes_fail = 0
23
- nb_meshes_success = 0
24
-
25
- missing_execution : list [str ] = list ()
26
- labelings_fail : list [str ] = list ()
27
- invalid_labelings : list [str ] = list ()
28
- valid_labelings_but_non_monotone : list [str ] = list ()
29
- valid_and_all_monotone_labelings : list [str ] = list ()
30
-
31
- per_labeling_feature_edges_stats : dict = dict ()
21
+ logging .getLogger ().setLevel (logging .INFO )
22
+
23
+ report_name = strftime ('%Y-%m-%d_%Hh%M_report' , localtime ())
24
+
25
+ # https://www.ag-grid.com/react-data-grid/getting-started/
26
+ HTML_report = f"""<!DOCTYPE html>
27
+ <html lang="en">
28
+ <head>
29
+ <title>{ report_name } </title>
30
+ <meta charSet="UTF-8"/>
31
+ <meta name="viewport" content="width=device-width, initial-scale=1"/>
32
+ <style media="only screen">
33
+ html, body {{
34
+ height: 100%;
35
+ width: 100%;
36
+ margin: 0;
37
+ box-sizing: border-box;
38
+ -webkit-overflow-scrolling: touch;
39
+ }}
40
+
41
+ html {{
42
+ position: absolute;
43
+ top: 0;
44
+ left: 0;
45
+ padding: 0;
46
+ overflow: auto;
47
+ }}
48
+
49
+ body {{
50
+ padding: 16px;
51
+ overflow: auto;
52
+ background-color: transparent
53
+ }}
54
+ </style>
55
+ </head>
56
+ <body style="text-align: center;">
57
+ <div id="myGrid" style="width: 100%; height: 100%" class="ag-theme-alpine-dark"></div>
58
+ <script src="https://cdn.jsdelivr.net/npm/[email protected] /dist/ag-grid-community.min.js"></script>
59
+ <script>
60
+ // Grid API: Access to Grid API methods
61
+ let gridApi;
62
+
63
+ // Grid Options: Contains all of the grid configurations
64
+ const gridOptions = {{
65
+ // Row Data: The data to be displayed.
66
+ rowData: [
67
+ """
32
68
33
69
root_folder = root ()
34
70
for level_minus_1_folder in [x for x in root_folder .path .iterdir () if x .is_dir ()]:
71
+ CAD_name = level_minus_1_folder .name
35
72
if not (level_minus_1_folder / step .FILENAMES .STEP ).exists ():
36
73
logging .warning (f"Folder { level_minus_1_folder } has no { step .FILENAMES .STEP } " )
37
74
continue
38
- nb_CAD += 1
39
75
if (level_minus_1_folder / 'Gmsh_0.1/' ).exists () and (level_minus_1_folder / 'Gmsh_0.1' / tet_mesh .FILENAMES .SURFACE_MESH_OBJ ).exists ():
40
- tet_folder = AbstractDataFolder .instantiate (level_minus_1_folder / 'Gmsh_0.1' )
41
- nb_meshes_success += 1
76
+ tet_folder : tet_mesh = AbstractDataFolder .instantiate (level_minus_1_folder / 'Gmsh_0.1' )
77
+ avg_edge_length = float ( tet_folder . get_mesh_stats_dict ()[ 'edges' ][ 'length' ][ 'avg' ])
42
78
labeling_subfolders_generated_by_automatic_polycube : list [Path ] = tet_folder .get_subfolders_generated_by ('automatic_polycube' )
43
79
assert (len (labeling_subfolders_generated_by_automatic_polycube ) <= 1 )
44
80
if len (labeling_subfolders_generated_by_automatic_polycube ) == 0 :
45
- missing_execution . append ( str ( level_minus_1_folder / 'Gmsh_0.1/' ))
81
+ HTML_report += f""" \n {{ name: " { CAD_name } ", avg_edge_length: { avg_edge_length :.3f } , valid: null, nb_turning_points: null, percentage_removed: null, percentage_lost: null, percentage_preserved: null }},"""
46
82
continue
47
83
relative_path = labeling_subfolders_generated_by_automatic_polycube [0 ].relative_to (root_folder .path )
48
84
if not (labeling_subfolders_generated_by_automatic_polycube [0 ] / labeling .FILENAMES .SURFACE_LABELING_TXT ).exists ():
49
- logging .warning (f"Folder { labeling_subfolders_generated_by_automatic_polycube [0 ] / labeling .FILENAMES .SURFACE_LABELING_TXT } has no { labeling .FILENAMES .SURFACE_LABELING_TXT } " )
50
- labelings_fail .append (relative_path )
85
+ HTML_report += f"""\n {{ name: "{ CAD_name } ", avg_edge_length: { avg_edge_length :.3f} , valid: null, nb_turning_points: null, percentage_removed: null, percentage_lost: null, percentage_preserved: null }},"""
51
86
continue
52
87
labeling_folder : labeling = AbstractDataFolder .instantiate (labeling_subfolders_generated_by_automatic_polycube [0 ])
53
88
assert (labeling_folder .type () == 'labeling' )
54
- stats = labeling_folder .get_labeling_stats_dict ()
55
- per_labeling_feature_edges_stats [relative_path ] = stats ['feature-edges' ]
56
- if not labeling_folder .has_valid_labeling ():
57
- invalid_labelings .append (relative_path )
58
- continue
59
- # valid labeling
60
- if labeling_folder .nb_turning_points () > 0 :
61
- valid_labelings_but_non_monotone .append (relative_path )
62
- continue
63
- valid_and_all_monotone_labelings .append (relative_path )
89
+ feature_edges_stats = labeling_folder .get_labeling_stats_dict ()['feature-edges' ]
90
+ total_feature_edges = feature_edges_stats ['removed' ] + feature_edges_stats ['lost' ] + feature_edges_stats ['preserved' ]
91
+ HTML_report += f"""\n {{ name: "{ CAD_name } ", avg_edge_length: { avg_edge_length :.3f} , valid: { str (labeling_folder .has_valid_labeling ()).lower ()} , nb_turning_points: { labeling_folder .nb_turning_points ()} , percentage_removed: { feature_edges_stats ['removed' ]/ total_feature_edges * 100 :.2f} , percentage_lost: { feature_edges_stats ['lost' ]/ total_feature_edges * 100 :.2f} , percentage_preserved: { feature_edges_stats ['preserved' ]/ total_feature_edges * 100 :.2f} }},"""
64
92
else :
65
- nb_meshes_fail += 1
66
-
67
- print ('# CAD' )
68
- print ('' )
69
- print (f'nb CAD = { nb_CAD } ' )
70
- print ('' )
71
-
72
- print ('# Tet meshes' )
73
- print ('' )
74
- print (f'nb meshes fail = { nb_meshes_fail } -> { nb_meshes_fail / nb_CAD * 100 } %' )
75
- print (f'nb meshes success = { nb_meshes_success } -> { nb_meshes_success / nb_CAD * 100 } %' )
76
- print ('' )
77
-
78
- print ('# Labelings' )
79
- print ('' )
80
-
81
- print ('## Missing execution' )
82
- print ('' )
83
- print (f'nb = { len (missing_execution )} -> { len (missing_execution )/ nb_CAD * 100 } %' )
84
- for rel_path in missing_execution :
85
- print (f'- { rel_path } ' )
86
- print ('' )
87
-
88
- print ('## Fails' )
89
- print ('' )
90
- print (f'nb = { len (labelings_fail )} -> { len (labelings_fail )/ nb_CAD * 100 } %' )
91
- for rel_path in labelings_fail :
92
- print (f'- { rel_path } ' )
93
- print ('' )
94
-
95
- print ('## Invalid' )
96
- print ('' )
97
- print (f'nb = { len (invalid_labelings )} -> { len (invalid_labelings )/ nb_CAD * 100 } %' )
98
- for rel_path in invalid_labelings :
99
- print (f'- { rel_path } ' )
100
- print ('' )
101
-
102
- print ('## Valid but non-monotone boundaries' )
103
- print ('' )
104
- print (f'nb = { len (valid_labelings_but_non_monotone )} -> { len (valid_labelings_but_non_monotone )/ nb_CAD * 100 } %' )
105
- for rel_path in valid_labelings_but_non_monotone :
106
- print (f'- { rel_path } ' )
107
- print ('' )
108
-
109
- print ('## Valid and non-monotone boundaries' )
110
- print ('' )
111
- print (f'nb = { len (valid_and_all_monotone_labelings )} -> { len (valid_and_all_monotone_labelings )/ nb_CAD * 100 } %' )
112
- for rel_path in valid_and_all_monotone_labelings :
113
- print (f'- { rel_path } ' )
114
- print ('' )
115
-
116
- print ('# Feature edges preservation' )
117
-
118
- for rel_path ,feature_edges_stats in per_labeling_feature_edges_stats .items ():
119
- total_nb_feature_edges = feature_edges_stats ['removed' ]+ feature_edges_stats ['lost' ]+ feature_edges_stats ['preserved' ]
120
- print (f'## Feature edges in { rel_path } ' )
121
- print ('' )
122
- print (f"- nb removed : { feature_edges_stats ['removed' ]} -> { feature_edges_stats ['removed' ]/ total_nb_feature_edges * 100 } %" )
123
- print (f"- nb lost : { feature_edges_stats ['lost' ]} -> { feature_edges_stats ['lost' ]/ total_nb_feature_edges * 100 } %" )
124
- print (f"- nb preserved : { feature_edges_stats ['preserved' ]} -> { feature_edges_stats ['preserved' ]/ total_nb_feature_edges * 100 } %" )
125
- print ('' ) # separation with empty line
93
+ HTML_report += f"""\n {{ name: "{ CAD_name } ", avg_edge_length: null, valid: null, nb_turning_points: null, percentage_removed: null, percentage_lost: null, percentage_preserved: null }},"""
94
+
95
+ HTML_report += """
96
+ ],
97
+ // Column Definitions: Defines & controls grid columns.
98
+ columnDefs: [
99
+ { field: "name", headerName: "CAD model", cellDataType: 'text' },
100
+ {
101
+ headerName: 'tet mesh',
102
+ children: [
103
+ { field: "avg_edge_length", headerName: "avg. edge length", cellDataType: 'number' },
104
+ ]
105
+ },
106
+ {
107
+ headerName: 'labeling',
108
+ children: [
109
+ { field: "valid", headerName: "valid", cellDataType: 'boolean' },
110
+ { field: "nb_turning_points", headerName: "#turning-points", cellDataType: 'number' },
111
+ ]
112
+ },
113
+ {
114
+ headerName: 'feature edges',
115
+ children: [
116
+ { field: "percentage_removed", headerName: "%age removed", cellDataType: 'number' },
117
+ { field: "percentage_lost", headerName: "%age lost", cellDataType: 'number' },
118
+ { field: "percentage_preserved", headerName: "%age preserved", cellDataType: 'number' },
119
+ ]
120
+ },
121
+ ],
122
+ };
123
+
124
+ // Create Grid: Create new grid within the #myGrid div, using the Grid Options object
125
+ gridApi = agGrid.createGrid(document.querySelector('#myGrid'), gridOptions);
126
+ </script>
127
+ </body>
128
+ </html>
129
+ """
130
+
131
+ with open (f'{ report_name } .html' ,'w' ) as HTML_file :
132
+ logging .info (f'Writing { report_name } .html...' )
133
+ HTML_file .write (HTML_report )
0 commit comments