|
17 | 17 | import pyTEMlib.probe_tools as pt |
18 | 18 |
|
19 | 19 |
|
20 | | -def make_holes(atoms: Atoms, n_holes: int, hole_size: float) -> Atoms: |
| 20 | +def make_holes(atoms, n_holes=1, hole_size=3.0): |
21 | 21 | """ |
22 | | - Create holes in an Atoms object by deleting atoms around randomly selected positions. |
23 | | -
|
24 | | - Parameters: |
25 | | - - atoms (ase.Atoms): The input Atoms object. |
26 | | - - n_holes (int): The number of holes to create. |
27 | | - - hole_size (float): The radius of each hole. |
28 | | -
|
| 22 | + Remove atoms in random holes from the structure. |
| 23 | + |
| 24 | + Args: |
| 25 | + atoms: ASE Atoms object |
| 26 | + n_holes: Number of holes to create |
| 27 | + hole_size: Radius of each hole in Angstroms |
| 28 | + |
29 | 29 | Returns: |
30 | | - - ase.Atoms: The modified Atoms object with holes. |
| 30 | + Modified Atoms object with holes created |
31 | 31 | """ |
32 | | - # Step 1: Randomly select n_holes atoms |
33 | | - num_atoms = len(atoms) |
34 | | - selected_indices = random.sample(range(num_atoms), n_holes) |
35 | | - |
36 | | - # Step 2: Find and delete atoms within radius hole_size |
37 | | - for index in selected_indices: |
38 | | - # Get the position of the selected atom |
39 | | - pos = atoms[index].position |
40 | | - |
41 | | - # Create a NeighborList to find atoms within hole_size |
42 | | - cutoffs = [hole_size / 2] * len(atoms) |
43 | | - nl = NeighborList(cutoffs, self_interaction=False, bothways=True) |
44 | | - nl.update(atoms) |
45 | | - |
46 | | - # Find atoms within hole_size around the selected atom |
47 | | - indices, offsets = nl.get_neighbors(index) |
48 | | - indices = indices.tolist() |
49 | | - |
50 | | - # Add the selected atom itself to the list of atoms to be deleted |
51 | | - indices.append(index) |
52 | | - |
53 | | - # Delete atoms by their indices |
54 | | - atoms = atoms[[atom.index for atom in atoms if atom.index not in indices]] |
55 | | - |
| 32 | + import random |
| 33 | + from ase.geometry import get_distances |
| 34 | + |
| 35 | + atoms = atoms.copy() |
| 36 | + |
| 37 | + if n_holes == 0 or len(atoms) == 0: |
| 38 | + return atoms |
| 39 | + |
| 40 | + # Randomly select hole centers |
| 41 | + n_holes = min(n_holes, len(atoms)) |
| 42 | + hole_centers_indices = random.sample(range(len(atoms)), n_holes) |
| 43 | + hole_centers = atoms.positions[hole_centers_indices] |
| 44 | + |
| 45 | + # Collect atoms to remove (work backwards to avoid index shifting) |
| 46 | + atoms_to_remove = [] |
| 47 | + for i, pos in enumerate(atoms.positions): |
| 48 | + for center in hole_centers: |
| 49 | + distance = np.linalg.norm(pos - center) |
| 50 | + if distance < hole_size and i not in hole_centers_indices: |
| 51 | + atoms_to_remove.append(i) |
| 52 | + break |
| 53 | + |
| 54 | + # Remove in reverse order to maintain valid indices |
| 55 | + for idx in sorted(atoms_to_remove, reverse=True): |
| 56 | + del atoms[idx] |
| 57 | + |
56 | 58 | return atoms |
57 | 59 |
|
58 | 60 | def rotate_xtal(xtal, angle): |
|
0 commit comments