Skip to content

Commit 8b047e6

Browse files
committed
CAP-ADD: implemented extra info geometries
1 parent b34ac88 commit 8b047e6

File tree

3 files changed

+227
-52
lines changed

3 files changed

+227
-52
lines changed

src/gh/components/DF_csv_exporter/code.py

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -66,44 +66,29 @@ def __init__(self):
6666
"export_dist",
6767
input_indx, X_cord, Y_cord)
6868

69-
def _get_id(self,
70-
idx: int,
71-
i_result: DFVizResults
72-
) -> str:
73-
""" Get the ID of the element """
74-
counter = 0
75-
76-
if self.prefix == "beam":
77-
return idx
78-
elif self.prefix == "joint":
79-
for idx_b, beam in enumerate(i_result.assembly.beams):
80-
for idx_j, joint in enumerate(beam.joints):
81-
if counter == idx:
82-
return f"{idx_b}--{idx_j}--{0}"
83-
counter += 1
84-
elif self.prefix == "joint_face":
85-
for idx_b, beam in enumerate(i_result.assembly.beams):
86-
for idx_j, joint in enumerate(beam.joints):
87-
for idx_f, face in enumerate(joint.faces):
88-
if counter == idx:
89-
return f"{idx_b}--{idx_j}--{idx_f}"
90-
counter += 1
91-
9269
def _prepare_row(self,
9370
idx: int,
9471
i_result: DFVizResults
95-
) -> typing.Dict:
72+
) -> typing.Dict[str, typing.Any]:
9673
"""
9774
Convert the results contained in the DFVizResults object to a dict to be written in the CSV file
9875
9976
:param idx: Index of the element
10077
:param i_result: DFVizResults object containing all the values
10178
102-
:return: Dict of values containng as keys the header and as items the values to be written in the CSV file
79+
:return: Dict of values containing as keys the header and as items the values to be written in the CSV file
10380
"""
10481
if i_result.sanity_check[idx].value != DFInvalidData.VALID.value:
10582
invalid_type = i_result.sanity_check[idx].name
106-
return [self._get_id(idx, i_result), invalid_type, invalid_type, invalid_type, invalid_type, invalid_type, invalid_type]
83+
return {
84+
f"{self.prefix} id": i_result.find_id(idx),
85+
"invalid_type": invalid_type,
86+
"min_deviation": invalid_type,
87+
"max_deviation": invalid_type,
88+
"std_deviation": invalid_type,
89+
"rmse": invalid_type,
90+
"mean": invalid_type
91+
}
10792

10893
distances = [round(value, 4) for value in i_result.distances[idx]]
10994
min_dev = round(i_result.distances_min_deviation[idx], 4)
@@ -112,27 +97,48 @@ def _prepare_row(self,
11297
rmse = round(i_result.distances_rmse[idx], 4)
11398
mean = round(i_result.distances_mean[idx], 4)
11499

115-
row: typing.Dict = {
116-
f"{self.prefix} id": self._get_id(idx, i_result),
100+
row: typing.Dict[str, typing.Any] = {
101+
f"{self.prefix} id": i_result.find_id(idx),
117102
"distances": distances,
118103
"min_deviation": min_dev,
119104
"max_deviation": max_dev,
120105
"std_deviation": std_dev,
121106
"rmse": rmse,
122107
"mean": mean
123108
}
109+
110+
# FIXME: find a good design system
111+
# Add extra geometric info based on analysis type
112+
if i_result.analysis_type == "beam":
113+
row.update({
114+
"beam_length": i_result.assembly.beams[idx].length
115+
})
116+
elif i_result.analysis_type == "joint":
117+
# NB:: for conviniency, if there is only one beam, we add the lenght of the beam i nthe joint csv analysis output
118+
if i_result.assembly.has_only_one_beam:
119+
row.update({
120+
"beam_length": i_result.assembly.beams[0].length
121+
})
122+
row.update({
123+
"joint_distance_to_beam_midpoint": i_result.assembly.compute_all_joint_distances_to_midpoint()[idx]
124+
})
125+
elif i_result.analysis_type == "joint_face":
126+
row.update({
127+
"jointface_angle": i_result.assembly.compute_all_joint_angles()[idx]
128+
})
129+
124130
return row
125131

126132
def _write_csv(self,
127133
csv_path: str,
128-
rows: typing.List[typing.Dict],
134+
rows: typing.List[typing.Dict[str, typing.Any]],
129135
is_writing_only_distances: bool = False
130136
) -> None:
131137
"""
132138
Write the CSV file
133139
134140
:param csv_path: Path of the CSV file
135-
:param rows: Dict of values to be written in the CSV file
141+
:param rows: List of dictionaries containing values to be written in the CSV file
136142
:param is_writing_only_distances: Flag to check if to write ONLY distances or the whole analysis
137143
138144
:return: None
@@ -157,20 +163,15 @@ def RunScript(self,
157163
i_file_name: str,
158164
i_export_seperate_files: bool,
159165
i_export_distances: bool,
160-
i_result):
166+
i_result: DFVizResults) -> None:
161167

162168
csv_analysis_path: str = None
163169
csv_distances_path: str = None
164170

165171
if i_dump:
166172
os.makedirs(i_export_dir, exist_ok=True)
167173

168-
if len(i_result.assembly.beams) == len(i_result.source):
169-
self.prefix = "beam"
170-
elif len(i_result.assembly.all_joints) == len(i_result.source):
171-
self.prefix = "joint"
172-
elif len(i_result.assembly.all_joint_faces) == len(i_result.source):
173-
self.prefix = "joint_face"
174+
self.prefix = i_result.analysis_type
174175

175176
if i_export_seperate_files:
176177
for idx in range(len(i_result.source)):

src/gh/diffCheck/diffCheck/df_error_estimation.py

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ class NumpyEncoder(json.JSONEncoder):
2626
def default(self, obj):
2727
if isinstance(obj, np.ndarray):
2828
return obj.tolist()
29+
elif isinstance(obj, Enum):
30+
return obj.value # or use obj.name if you prefer
2931
return super().default(obj)
3032

3133
class DFInvalidData(Enum):
@@ -41,7 +43,7 @@ class DFInvalidData(Enum):
4143

4244
class DFVizResults:
4345
"""
44-
This class compiles the resluts of the error estimation into one object
46+
This class compiles the results of the error estimation into one object
4547
"""
4648
__serial_file_extenion: str = ".diffCheck"
4749

@@ -61,6 +63,8 @@ def __init__(self, assembly):
6163
self.distances_sd_deviation = []
6264
self.distances = []
6365

66+
self._analysis_type: str = None
67+
6468
def __repr__(self):
6569
return f"DFVizResults of({self.assembly})"
6670

@@ -109,7 +113,8 @@ def dump_serialization(self, dir: str) -> str:
109113

110114
timestamp: str = datetime.now().strftime("%Y%m%d_%H%M%S")
111115
assembly_name: str = self.assembly.name
112-
serial_file_path = os.path.join(dir, f"{assembly_name}_{timestamp}{self.__serial_file_extenion}")
116+
result_type: str = self.analysis_type
117+
serial_file_path = os.path.join(dir, f"{assembly_name}_{result_type}_{timestamp}{self.__serial_file_extenion}")
113118

114119
try:
115120
with open(serial_file_path, "w") as f:
@@ -135,6 +140,49 @@ def load_serialization(file_path: str) -> 'DFVizResults':
135140
raise e
136141
return obj
137142

143+
def _compute_dfresult_type(self):
144+
"""
145+
Detect if the DFVizResults object contains results of beam, joint of joint_face level analysis
146+
"""
147+
# check that source and target have the same length
148+
if len(self.source) != len(self.target):
149+
raise ValueError("Source and target have different length, cannot determine the type of analysis")
150+
if len(self.assembly.beams) == len(self.source):
151+
self._analysis_type = "beam"
152+
elif len(self.assembly.all_joints) == len(self.source):
153+
self._analysis_type = "joint"
154+
elif len(self.assembly.all_joint_faces) == len(self.source):
155+
self._analysis_type = "joint_face"
156+
return self._analysis_type
157+
158+
def find_id(self, idx: int,) -> str:
159+
"""
160+
Return the ID in str format of the element. This func is used during
161+
the csv export. With the following format:
162+
- beam: idx
163+
- joint: idx_b--idx_j--0
164+
- joint_face: idx_b--idx_j--idx_f
165+
166+
:param idx: the index of the element
167+
"""
168+
counter = 0
169+
170+
if self.analysis_type == "beam":
171+
return str(idx)
172+
elif self.analysis_type == "joint":
173+
for idx_b, beam in enumerate(self.assembly.beams):
174+
for idx_j, joint in enumerate(beam.joints):
175+
if counter == idx:
176+
return f"{idx_b}--{idx_j}--{0}"
177+
counter += 1
178+
elif self.analysis_type == "joint_face":
179+
for idx_b, beam in enumerate(self.assembly.beams):
180+
for idx_j, joint in enumerate(beam.joints):
181+
for idx_f, face in enumerate(joint.faces):
182+
if counter == idx:
183+
return f"{idx_b}--{idx_j}--{idx_f}"
184+
counter += 1
185+
return ""
138186

139187
def add(self, source, target, distances, sanity_check: DFInvalidData = DFInvalidData.VALID):
140188

@@ -215,6 +263,11 @@ def filter_values_based_on_valuetype(self, settings):
215263
def is_source_cloud(self):
216264
return type(self.source[0]) is diffcheck_bindings.dfb_geometry.DFPointCloud
217265

266+
@property
267+
def analysis_type(self):
268+
self._analysis_type = self._compute_dfresult_type()
269+
return self._analysis_type
270+
218271
# FIXME: ths is currently broken, we need to fix it
219272
def df_cloud_2_df_cloud_comparison(
220273
assembly: DFAssembly,

0 commit comments

Comments
 (0)