| 258 | json.dump(clash_sets, clashes_file, indent=4) |
| 259 | |
| 260 | def smart_group_clashes(self, clash_sets: list[ClashSet], max_clustering_distance: float): |
| 261 | from collections import defaultdict |
| 262 | |
| 263 | from sklearn.cluster import OPTICS |
| 264 | |
| 265 | count_of_input_clashes = 0 |
| 266 | count_of_clash_sets = 0 |
| 267 | count_of_smart_groups = 0 |
| 268 | count_of_final_clash_sets = 0 |
| 269 | |
| 270 | count_of_clash_sets = len(clash_sets) |
| 271 | |
| 272 | for clash_set in clash_sets: |
| 273 | if not "clashes" in clash_set.keys(): |
| 274 | self.settings.logger.info( |
| 275 | f"Skipping clash set [{clash_set['name']}] since it contains no clash results." |
| 276 | ) |
| 277 | continue |
| 278 | clashes = clash_set["clashes"] |
| 279 | if len(clashes) == 0: |
| 280 | self.settings.logger.info( |
| 281 | f"Skipping clash set [{clash_set['name']}] since it contains no clash results." |
| 282 | ) |
| 283 | continue |
| 284 | |
| 285 | count_of_input_clashes += len(clashes) |
| 286 | |
| 287 | positions = [] |
| 288 | for clash in clashes.values(): |
| 289 | positions.append(clash["position"]) |
| 290 | |
| 291 | data = np.array(positions) |
| 292 | |
| 293 | # INPUTS |
| 294 | # set the desired maximum distance between the grouped points |
| 295 | if max_clustering_distance > 0: |
| 296 | max_distance_between_grouped_points = max_clustering_distance |
| 297 | else: |
| 298 | max_distance_between_grouped_points = 3 |
| 299 | |
| 300 | model = OPTICS(min_samples=2, max_eps=max_distance_between_grouped_points) |
| 301 | model.fit_predict(data) |
| 302 | pred = model.fit_predict(data) |
| 303 | |
| 304 | # Insert the smart groups into the clashes |
| 305 | if len(pred) == len(clashes.values()): |
| 306 | i = 0 |
| 307 | for clash in clashes.values(): |
| 308 | int_prediction = int(pred[i]) |
| 309 | if int_prediction == -1: |
| 310 | # ungroup this clash since it's a single clash that we were not able to group. |
| 311 | new_clash_group_number = np.amax(pred).item() + 1 + i |
| 312 | clash["smart_group"] = new_clash_group_number |
| 313 | else: |
| 314 | clash["smart_group"] = int_prediction |
| 315 | i += 1 |
| 316 | |
| 317 | # Create JSON with smart_groups that contain GlobalIDs |