@@ -124,7 +124,7 @@ def get_region(
124124 neighbour_factors ,
125125 search_mask ,
126126 ) = self ._find_possible_bases (system , seed_index )
127- proto_cell , offset , dim = self ._find_proto_cell (
127+ proto_cell , offset , dim , n_periodic_spans_selected = self ._find_proto_cell (
128128 system ,
129129 seed_index ,
130130 possible_spans ,
@@ -153,7 +153,11 @@ def get_region(
153153
154154 i_indices = unit_collection .get_basis_indices ()
155155
156- if len (i_indices ) > 0 :
156+ # The region is accepted if it either has more than 1+dim atoms in
157+ # it or one of the spans is periodic. In many cases the prototype
158+ # cell can be found (seed + number of spans), but it cannot really
159+ # be extended to cover any significant portion of the system.
160+ if len (i_indices ) > 1 + dim or n_periodic_spans_selected >= 1 :
157161 region = unit_collection
158162 region ._pos_tol = pos_tol
159163
@@ -223,6 +227,8 @@ def _find_proto_cell(
223227 Returns:
224228 ase.Atoms: A system representing the best cell that was found
225229 np.ndarray: Position of the seed atom in the cell
230+ int: Dimensionality of the found system
231+ int: Number of periodic unit cell vectors used
226232 """
227233 positions = system .get_positions ()
228234 numbers = system .get_atomic_numbers ()
@@ -342,18 +348,26 @@ def _find_proto_cell(
342348 | (metric >= 0.75 * n_neighbours )
343349 )[0 ]
344350
345- if len (valid_span_indices ) == 0 :
346- return None , None , None
351+ total_valid_spans = len (valid_span_indices )
352+ if total_valid_spans == 0 :
353+ return None , None , None , None
347354
348355 # Find the best basis
349356 valid_span_metrics = metric [valid_span_indices ]
350357 valid_spans = possible_spans [valid_span_indices ]
351358 best_combo = self ._find_best_basis (valid_spans , valid_span_metrics )
352359 dim = len (best_combo )
353360
361+ # Check how many of the periodic spans are still selected as prototype
362+ # unit cell vectors
363+ selected_spans = range (total_valid_spans - n_periodic_spans , total_valid_spans )
364+ n_periodic_spans_selected = sum (
365+ span_index in best_combo for span_index in selected_spans
366+ )
367+
354368 # Currently 1D is not handled
355369 if dim == 1 :
356- return None , None , 1
370+ return None , None , 1 , None
357371
358372 best_spans = valid_spans [best_combo ]
359373 n_spans = len (best_spans )
@@ -382,7 +396,7 @@ def _find_proto_cell(
382396
383397 # If the seed atom is not in a valid graph, no region could be found.
384398 if seed_group_index is None :
385- return None , None , None
399+ return None , None , None , None
386400
387401 # Notice that the seed group index can get updated by the cell search if
388402 # an atom is dropped out of the cell due to appearing too infrequently.
@@ -409,7 +423,7 @@ def _find_proto_cell(
409423 pos_tol ,
410424 )
411425 if proto_cell is None :
412- return None , None , None
426+ return None , None , None , None
413427
414428 two_valid_spans = n_spans == 2
415429 if n_spans == 3 :
@@ -424,7 +438,7 @@ def _find_proto_cell(
424438 proto_cell , bond_threshold
425439 )
426440 except MatIDError :
427- return None , None , None
441+ return None , None , None , None
428442 if dimensionality != 3 :
429443 # Try if the cell can be "reduced" to a 2D material
430444 if dimensionality == 2 :
@@ -458,20 +472,18 @@ def _find_proto_cell(
458472 two_valid_spans = True
459473 n_spans = 2
460474 else :
461- return None , None , None
475+ return None , None , None , None
462476
463477 if two_valid_spans :
464478 # If the best 2D vectors consists only of the simulation basis cell
465479 # vectors, check that these vectors are below a predefined size.
466480 # Otherwise the cell cannot be accepted because there is not enough
467481 # statistics about the cell contents to distinguish outliers.
468482 if n_periodic_spans > 0 :
469- periodic_span_indices = valid_span_indices [- n_periodic_spans :]
470- best_span_ind = valid_span_indices [best_combo ]
471- if set (best_span_ind ).issubset (set (periodic_span_indices )):
483+ if n_periodic_spans_selected == 2 :
472484 cell_lens = np .linalg .norm (best_spans , axis = 1 )
473485 if np .any (cell_lens > self .max_2d_single_cell_size ):
474- return None , None , None
486+ return None , None , None , None
475487
476488 # Check the dimensionality
477489 dimensionality , cluster_labels = matid .geometry .get_dimensionality (
@@ -482,7 +494,7 @@ def _find_proto_cell(
482494 # has multiple stacked 2D sheets with identical periodicity. In
483495 # this case the unit cell should only comprise of atoms in the
484496 # cluster where the seed atom is in.
485- for i_index , i_cluster in enumerate ( cluster_labels ) :
497+ for i_cluster in cluster_labels :
486498 try :
487499 seed_group_index = i_cluster .index (seed_group_index )
488500 except ValueError :
@@ -498,13 +510,13 @@ def _find_proto_cell(
498510 proto_cell , bond_threshold
499511 )
500512 if dimensionality is None :
501- return None , None , None
513+ return None , None , None , None
502514 else :
503515 if dimensionality != 2 :
504- return None , None , None
516+ return None , None , None , None
505517 else :
506518 if dimensionality != 2 :
507- return None , None , None
519+ return None , None , None , None
508520
509521 # Check the cell thickness. 2D materials that are thicker than a
510522 # specified threshold are not accepted.
@@ -514,16 +526,16 @@ def _find_proto_cell(
514526 offset = proto_cell .get_positions ()[seed_group_index ]
515527 thickness = matid .geometry .get_thickness (proto_cell , 2 )
516528 if thickness > self .max_2d_cell_height :
517- return None , None , None
529+ return None , None , None , None
518530
519531 # Check that the final proto cell atoms don't overlap
520532 if proto_cell is not None :
521533 dist_proto_cell = matid .geometry .get_distances (proto_cell ).dist_matrix_mic
522534 dist_proto_cell = dist_proto_cell [np .triu_indices (dist_proto_cell .shape [0 ])]
523535 if dist_proto_cell .min () < overlap_threshold :
524- return None , None , None
536+ return None , None , None , None
525537
526- return proto_cell , offset , n_spans
538+ return proto_cell , offset , n_spans , n_periodic_spans_selected
527539
528540 def _find_graphs (
529541 self ,
0 commit comments