Source code for ipsuite.configuration_selection.threshold
"""Selecting atoms with a given step between them."""importtypingimportaseimportmatplotlib.pyplotaspltimportnumpyasnpimportzntrackfromipsuite.configuration_selectionimportConfigurationSelection
[docs]defcheck_dimension(values):ifvalues.ndim>1:raiseValueError(f"Value dimension is {values.ndim} != 1. ""Reduce the dimension by defining dim_reduction, ""use mean or max to get (n_structures,) shape.")
[docs]classThresholdSelection(ConfigurationSelection):"""Select atoms based on a given threshold. Select atoms above a given threshold or the n_configurations with the highest / lowest value. Typically useful for uncertainty based selection. Attributes ---------- key: str The key in 'calc.results' to select from threshold: float, optional All values above (or below if negative) this threshold will be selected. If n_configurations is given, 'self.threshold' will be prioritized, but a maximum of n_configurations will be selected. reference: str, optional For visualizing the selection a reference value can be given. For 'energy_uncertainty' this would typically be 'energy'. n_configurations: int, optional Number of configurations to select. min_distance: int, optional Minimum distance between selected configurations. dim_reduction: str, optional Reduces the dimensionality of the chosen uncertainty along the specified axis by calculating either the maximum or mean value. Choose from ["max", "mean"] reduction_axis: tuple(int), optional Specifies the axis along which the reduction occurs. """key:str=zntrack.params("energy_uncertainty")reference:str=zntrack.params("energy")threshold:float|None=zntrack.params(None)n_configurations:int|None=zntrack.params(None)min_distance:int=zntrack.params(1)dim_reduction:str=zntrack.params(None)reduction_axis:list[int]=zntrack.params((1,2))def__post_init__(self):ifself.thresholdisNoneandself.n_configurationsisNone:raiseValueError("Either 'threshold' or 'n_configurations' must not be None.")
[docs]defselect_atoms(self,atoms_lst:typing.List[ase.Atoms],save_fig:bool=True)->typing.List[int]:"""Take every nth (step) object of a given atoms list. Parameters ---------- atoms_lst: typing.List[ase.Atoms] list of atoms objects to arange Returns ------- typing.List[int]: list containing the taken indices """self.reduction_axis=tuple(self.reduction_axis)values=np.array([atoms.calc.results[self.key]foratomsinatoms_lst])ifself.dim_reductionisnotNone:reduction_fn=REDUCTIONS[self.dim_reduction]values=reduction_fn(values,self.reduction_axis)check_dimension(values)ifself.thresholdisnotNone:ifself.threshold<0:indices=np.where(values<self.threshold)[0]ifself.n_configurationsisnotNone:indices=np.argsort(values)[indices]else:indices=np.where(values>self.threshold)[0]ifself.n_configurationsisnotNone:indices=np.argsort(values)[::-1][indices]else:ifnp.mean(values)>0:indices=np.argsort(values)[::-1]else:indices=np.argsort(values)selection=[]forvalinindices:# If the value is close to any of the already selected values, skip it.ifnotany(np.abs(val-np.array(selection))<self.min_distance):selection.append(int(val))iflen(selection)==self.n_configurations:breakreturnselection