def test_from_npoints_plane(self): best_fits = ['least_square_distance', 'maximum_distance'] delta = 0.0001 for best_fit in best_fits: plane = Plane.from_npoints([self.p1, self.p2, self.p3], best_fit=best_fit) self.assertTrue(self.plane.is_same_plane_as(plane)) points = [ np.array([5.1, 0.3, -2.3]), np.array([-2.0, 4.3, -6.3]), np.array([3.1, 2.3, -21.3]), np.array([-2, -0.5, 0.05]), np.array([11, 12, -13]), np.array([10, 8.3, -6.32]) ] plane = Plane.from_npoints(points, best_fit=best_fit) fit_error_plane = plane.fit_error(points, fit=best_fit) coeffs = [[1.0 + delta, 1, 1, 1], [1, 1.0 + delta, 1, 1], [1, 1, 1.0 + delta, 1], [1, 1, 1, 1.0 + delta], [1.0 - delta, 1.0 + delta, 1.0 - delta, 1.0 + delta]] for coeff in coeffs: plane_changed = Plane.from_coefficients( coeff[0] * plane.a, coeff[1] * plane.b, coeff[2] * plane.c, coeff[3] * plane.d) fit_error = plane_changed.fit_error(points, fit=best_fit) self.assertGreater(fit_error, fit_error_plane) coeff = [-2.1, -2.1, -2.1, -2.1] plane_not_changed = Plane.from_coefficients( coeff[0] * plane.a, coeff[1] * plane.b, coeff[2] * plane.c, coeff[3] * plane.d) fit_error = plane_not_changed.fit_error(points, fit=best_fit) self.assertAlmostEqual(fit_error, fit_error_plane)
def test_from_npoints_plane(self): best_fits = ['least_square_distance', 'maximum_distance'] delta = 0.0001 for best_fit in best_fits: plane = Plane.from_npoints([self.p1, self.p2, self.p3], best_fit=best_fit) self.assertTrue(self.plane.is_same_plane_as(plane)) points = [np.array([5.1, 0.3, -2.3]), np.array([-2.0, 4.3, -6.3]), np.array([3.1, 2.3, -21.3]), np.array([-2, -0.5, 0.05]), np.array([11, 12, -13]), np.array([10, 8.3, -6.32])] plane = Plane.from_npoints(points, best_fit=best_fit) fit_error_plane = plane.fit_error(points, fit=best_fit) coeffs = [[1.0+delta, 1, 1, 1], [1, 1.0+delta, 1, 1], [1, 1, 1.0+delta, 1], [1, 1, 1, 1.0+delta], [1.0-delta, 1.0+delta, 1.0-delta, 1.0+delta]] for coeff in coeffs: plane_changed = Plane.from_coefficients(coeff[0]*plane.a, coeff[1]*plane.b, coeff[2]*plane.c, coeff[3]*plane.d) fit_error = plane_changed.fit_error(points, fit=best_fit) self.assertGreater(fit_error, fit_error_plane) coeff = [-2.1, -2.1, -2.1, -2.1] plane_not_changed = Plane.from_coefficients(coeff[0]*plane.a, coeff[1]*plane.b, coeff[2]*plane.c, coeff[3]*plane.d) fit_error = plane_not_changed.fit_error(points, fit=best_fit) self.assertAlmostEqual(fit_error, fit_error_plane)
cg_points = [myfactor * np.array(pp) for pp in cg.points] cg_central_site = myfactor * np.array(cg.central_site) if sepplane: pts = [cg_points[ii] for ii in algo.plane_points] if algo.minimum_number_of_points == 2: pts.append(cg_central_site) centre = cg_central_site else: centre = np.sum(pts, axis=0) / len(pts) factor = 1.5 target_dist = max( [np.dot(pp - centre, pp - centre) for pp in cg_points]) current_dist = np.dot(pts[0] - centre, pts[0] - centre) factor = factor * target_dist / current_dist plane = Plane.from_npoints(points=pts) p1 = centre + factor * (pts[0] - centre) perp = factor * np.cross(pts[0] - centre, plane.normal_vector) p2 = centre + perp p3 = centre - factor * (pts[0] - centre) p4 = centre - perp vis.add_faces([[p1, p2, p3, p4]], [1.0, 0.0, 0.0], opacity=0.5) target_radius = 0.25 radius = myfactor * ( target_radius - 0.2 ) / 0.002 # due to how the radius is obtained in add_partial_sphere # of pymatgen if algo.minimum_number_of_points == 2:
continue local_plane = Plane.from_3points( points_combination[0], points_combination[1], lgf.local_geometry.central_site ) found = True break elif npoints == 3: if collinear(points_combination[0], points_combination[1], points_combination[2], tolerance=0.25): continue local_plane = Plane.from_3points( points_combination[0], points_combination[1], points_combination[2] ) found = True break elif npoints > 3: local_plane = Plane.from_npoints(points_combination, best_fit="least_square_distance") found = True break else: raise ValueError("Wrong number of points to initialize separation plane") points_perfect = lgf.perfect_geometry.points_wocs_ctwocc() # Actual test of the permutations cgsm = lgf._cg_csm_separation_plane( coordination_geometry=cg, sepplane=sepplanealgo, local_plane=local_plane, plane_separations=[], dist_tolerances=[0.05, 0.1, 0.2, 0.3], testing=True, points_perfect=points_perfect,
algo._permutations = permutations print('Safe permutations found ({:d})'.format(len(permutations))) # Definition of the planes all_planes_point_indices = [algo.plane_points] if algo.other_plane_points is not None: all_planes_point_indices.extend(algo.other_plane_points) # Loop on the planes explicit_permutations_per_plane = [] for iplane, plane_point_indices in enumerate(all_planes_point_indices): prt1(string='In plane {:d} ({})'.format(iplane, '-'.join(str(pp) for pp in plane_point_indices)), printing_volume=printing_volume) points_combination = [lgf.local_geometry._coords[ii] for ii in plane_point_indices] local_plane = Plane.from_npoints(points_combination, best_fit='least_square_distance') # Actual test of the permutations csms, perms, algos, sep_perms = lgf._cg_csm_separation_plane(coordination_geometry=cg, sepplane=algo, local_plane=local_plane, plane_separations=[], dist_tolerances=[0.05, 0.1, 0.2, 0.3], testing=True, points_perfect=points_perfect) prt1(string='Continuous symmetry measures', printing_volume=printing_volume) prt1(string=csms, printing_volume=printing_volume) csms_with_recorded_permutation = [] explicit_permutations = []
vis = visualize(cg=cg, vis=vis, myfactor=myfactor) cg_points = [myfactor*np.array(pp) for pp in cg.points] cg_central_site = myfactor*np.array(cg.central_site) if sepplane: pts = [cg_points[ii] for ii in algo.plane_points] if algo.minimum_number_of_points == 2: pts.append(cg_central_site) centre = cg_central_site else: centre = np.sum(pts, axis=0) / len(pts) factor = 1.5 target_dist = max([np.dot(pp-centre, pp-centre) for pp in cg_points]) current_dist = np.dot(pts[0] - centre, pts[0] - centre) factor = factor * target_dist / current_dist plane = Plane.from_npoints(points=pts) p1 = centre + factor * (pts[0] - centre) perp = factor * np.cross(pts[0] - centre, plane.normal_vector) p2 = centre + perp p3 = centre - factor * (pts[0] - centre) p4 = centre - perp vis.add_faces([[p1, p2, p3, p4]], [1.0, 0.0, 0.0], opacity=0.5) target_radius = 0.25 radius = 1.5 * target_radius if algo.minimum_number_of_points == 2: vis.add_partial_sphere(coords=cg_central_site, radius=radius, color=[1.0, 0.0, 0.0], start=0, end=360, opacity=0.5)